diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index 4644326e6e..62105f110a 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -24,10 +24,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '21' distribution: 'temurin' cache: 'maven' diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml index 4fe4df9144..ca62d454f4 100644 --- a/.github/workflows/maven-deploy.yml +++ b/.github/workflows/maven-deploy.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 8 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: - java-version: '8' + java-version: '21' distribution: 'temurin' cache: 'maven' server-id: ossrh @@ -43,4 +43,4 @@ jobs: env: MAVEN_USERNAME: ${{ secrets.MAVEN_USER }} MAVEN_PASSWORD: ${{ secrets.MAVEN_TOKEN }} - MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} \ No newline at end of file + MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }} diff --git a/JDK21_UPGRADE_PLAN.md b/JDK21_UPGRADE_PLAN.md new file mode 100644 index 0000000000..2f68e3597f --- /dev/null +++ b/JDK21_UPGRADE_PLAN.md @@ -0,0 +1,210 @@ +# CAT JDK 21 升级计划 + +## 目标 + +将当前 CAT 工程升级到 JDK 21 构建和运行,替换高风险历史依赖,并逐步从“外置 Tomcat + WAR”部署方式迁移到“JDK 21 + 可执行 JAR + 内嵌容器”部署方式。 + +这次升级不只改版本号。项目仍依赖 `javax.servlet`、`web.xml`、Unidal MVC、Plexus 组件、JSP、历史 Log4j 1.x API 和 MySQL/Netty/Hadoop 等基础库。升级需要分阶段推进,每个阶段都要保持可编译、可测试、可打包、可启动。 + +## 当前推荐路线 + +推荐采用“两步容器迁移”: + +1. 先把工程构建、运行时和主要基础依赖升级到 JDK 21 可用状态。 +2. 新增 `cat-boot` 过渡模块,用 Spring Boot 4 稳定版作为启动外壳,但 Web 容器暂时锁定在 Tomcat 9 线,继续兼容现有 `javax.servlet` / JSP / Unidal MVC。 +3. Docker 从外置 Tomcat 镜像切换为 JDK 21 runtime 镜像,通过 `java -jar /app/cat-boot.jar` 启动。 +4. 后续单独评估 Jakarta 迁移,确认 Unidal MVC、JSP、Servlet Filter 和插件体系可行后,再考虑真正切换到 Spring Boot 4 原生 Jakarta Web 栈。 + +不建议第一步直接把现有 Web 层 Jakarta 化。Spring Boot 4 的 Web 生态基于 Jakarta Servlet,而当前项目大量代码和依赖仍是 `javax.servlet`,直接切换会把 JDK、容器、MVC、JSP、Filter、依赖树问题混在一起,风险过高。 + +## 已完成的升级项 + +### 1. JDK 21 构建基线 + +- 根 POM 已改为 `21`。 +- Maven Enforcer 已要求 Java `[21,22)` 和 Maven `[3.9.0,)`。 +- Maven 插件已升级到 JDK 21 兼容版本,包括 compiler、surefire、war、shade、source、javadoc、enforcer。 +- GitHub Actions 已从 JDK 8 切换到 JDK 21。 +- Docker 构建镜像已切换到 `maven:3.9.12-eclipse-temurin-21`。 + +### 2. 测试兼容性修复 + +- 修复 `DefaultMessageTree.copyForTest()` 对消息长度头的处理,并释放 `ByteBuf`。 +- `PlainTextMessageCodec` 解码后补充完成态设置。 +- 多个 consumer analyzer 测试补充 `setCompleted()`。 +- `TaskHelperTest` 移除 PowerMock,用普通 JUnit/Mockito 风格验证。 +- `StateAnalyzer` 增加测试所需的 `setMIp(String ip)`。 + +### 3. 日志组件迁移到 Logback + +- Logback 已升级到 `1.5.34`。 +- SLF4J 使用 `2.0.17` 稳定线。 +- 服务端模块引入 `logback-classic` 和 `log4j-over-slf4j`。 +- 排除 Hadoop 传递进来的旧 `slf4j-log4j12` 和 `log4j`。 +- 新增 `cat-home/src/main/resources/logback.xml`。 +- 测试模块新增 `logback-test.xml` 或测试用 `log4j.properties`,避免测试日志绑定冲突。 +- 保留 `log4j:log4j` 的 optional/provided 兼容依赖,用于 CAT 客户端对外暴露的 Log4j 1.x Appender API;它不应作为服务端运行时日志实现。 + +### 4. JSON 组件迁移到 fastjson2 + +- `com.alibaba:fastjson` 已替换为 `com.alibaba.fastjson2:fastjson2`。 +- fastjson2 已升级到 `2.0.62`。 +- 当前源码未发现直接使用 `com.alibaba.fastjson.*` import,本阶段主要是依赖坐标迁移。 + +### 5. 低风险依赖升级 + +- JUnit 升级到 `4.13.2`。 +- Netty 升级到 `4.1.128.Final`,不采用 Netty 5 alpha。 +- Gson 升级到 `2.13.2`。 +- HttpClient/HttpMime 升级到 `4.5.14`。 +- Commons Codec 升级到 `1.19.0`。 +- Snappy 升级到 `1.1.10.8`。 +- Freemarker 升级到 `2.3.34`。 +- c3p0 升级到 `0.11.2`。 +- Plexus Utils 升级到 `4.0.2`。 +- java-saml 升级到 `2.9.0`。 +- MySQL 驱动坐标从 `mysql:mysql-connector-java` 切换为 `com.mysql:mysql-connector-j:9.7.0`。 +- MySQL 驱动类配置更新为 `com.mysql.cj.jdbc.Driver`。 + +### 6. Spring Boot 过渡启动模块 + +- 新增 `cat-boot` 模块。 +- `cat-boot` 引入 Spring Boot `4.0.2` 稳定版作为启动外壳。 +- `cat-boot` 显式使用 `tomcat-embed-core` / `tomcat-embed-jasper` `9.0.112`,继续兼容现有 `javax.servlet` Web 层。 +- `cat-boot` 打包时复制 `cat-home.war` 到 classpath,并通过 shade 生成可执行 JAR。 +- `CatBootApplication` 启动 Spring Boot 后,由 `EmbeddedCatServer` 解出 `cat-home.war` 并部署到 `/cat`。 +- shade 配置已排除 `META-INF/*.SF`、`META-INF/*.DSA`、`META-INF/*.RSA`,避免 JDK 21 下 fat jar 签名校验失败。 + +### 7. Docker 运行方式切换 + +- Docker runtime 镜像已从 Tomcat/JRE 8 切换为 `eclipse-temurin:21-jre`。 +- Docker 运行入口已改为 `java -Dcat.home=/data/appdatas/cat -Dserver.port=8080 -jar /app/cat-boot.jar`。 +- `docker-compose.yml` 已改为基于当前 Dockerfile 构建 `cat:4.0-RC1-jdk21`,不再默认拉取旧的 `meituaninc/cat:3.0.1` 镜像。 + +## 当前验证结果 + +已通过的验证: + +- `mvn -pl cat-consumer -am test` +- `mvn -pl cat-alarm -am test` +- `mvn -pl cat-boot -am package -DskipTests` +- `mvn package -DskipTests` +- `mvn test` +- `java -Dserver.port=0 -jar cat-boot/target/cat-boot-4.0-RC1.jar` 短启动验证 +- `java -Dcat.home=.tmp-cat-home -Dserver.port=18080 -jar cat-boot/target/cat-boot-4.0-RC1.jar` 短启动和 HTTP 探测 + +短启动中已确认: + +- Spring Boot `4.0.2` 启动。 +- Embedded Tomcat `9.0.112` 启动。 +- CAT Web 应用部署到 `/cat`。 +- Netty receiver 启动日志出现。 +- 本地未配置 `datasources.xml` / `server.xml` 时会出现数据源缺失日志,这是运行环境配置问题,不是构建失败。 +- 使用临时 `cat.home` 访问 `/cat/r` 可到达 Web 层,但返回 500;堆栈指向缺少数据源和 top service 注册,不是 Spring Boot/Tomcat 启动失败。 +- 当前机器未安装或未暴露 `docker` 命令,Docker build/compose 端到端验证尚未执行。 + +## 待完成验证 + +### 1. 全量打包复验 + +在最终提交前继续执行: + +```bash +mvn package -DskipTests +``` + +通过后确认: + +- `cat-home/target/cat-home-4.0-RC1.war` 存在。 +- `cat-boot/target/cat-boot-4.0-RC1.jar` 存在。 + +### 2. Docker 构建验证 + +需要在可用 Docker 环境中执行: + +```bash +docker build -f docker/Dockerfile . +``` + +验收标准: + +- Maven 构建阶段成功。 +- runtime 镜像只依赖 JDK 21 runtime,不依赖外置 Tomcat。 +- 镜像内存在 `/app/cat-boot.jar`。 + +### 3. Docker Compose 端到端验证 + +需要执行: + +```bash +docker compose -f docker/docker-compose.yml up --build +``` + +验收标准: + +- MySQL 容器启动并初始化 `cat` schema。 +- CAT 容器启动成功。 +- `8080` Web 端口可访问。 +- `2280` TCP 接收端口可监听。 +- `/cat/r`、`/cat/s` 等路由可访问。 +- JSP 页面和静态资源可正常加载。 +- Logback 日志正常输出。 +- JSON 输出结构保持兼容。 + +### 4. 带真实配置的运行冒烟 + +需要提供或挂载真实配置: + +- `client.xml` +- `server.xml` +- `datasources.xml` + +验收标准: + +- MySQL 数据源初始化成功。 +- 服务端能写入和读取 CAT 配置。 +- 客户端上报链路可打通。 +- 报表页面可访问。 +- 告警配置和通知链路无启动异常。 + +## 仍需单独评估的升级项 + +### 1. Jakarta / Spring Boot 原生 Web 栈迁移 + +当前 `cat-boot` 是过渡方案,不等于已经完成 Spring Boot 4 原生 Web 迁移。后续需要单独评估: + +- `javax.servlet.*` 到 `jakarta.servlet.*` 的代码迁移。 +- `web.xml` namespace 和 Servlet/JSP/JSTL 依赖迁移。 +- Unidal MVC 是否支持 Jakarta。 +- Plexus 组件初始化顺序是否受影响。 +- JSP 在新容器中的渲染兼容性。 +- Filter dispatch、权限过滤、Domain 过滤是否保持兼容。 + +### 2. Unidal 升级 + +Maven 版本检查显示 Unidal framework 有 4.x 线,但它影响 MVC、Plexus、DAL、代码生成和运行时组件,不应和当前 JDK/Spring Boot 过渡升级混在一起。建议后续单独开分支验证。 + +### 3. Hadoop 升级 + +Hadoop `2.4.1` 到 3.x 是高风险升级,会影响 HDFS/logview 相关行为和传递依赖。建议单独处理,并补充 HDFS 场景验证。 + +### 4. 历史兼容 API + +CAT 客户端仍对外提供 Log4j 1.x Appender 等历史集成 API。服务端运行时可以迁移到 Logback,但客户端 API 是否彻底移除需要单独评估兼容性和用户影响。 + +## 提交拆分建议 + +建议按以下顺序拆分提交: + +1. JDK 21 构建基线、Maven 插件、CI 配置。 +2. JDK 21 下的测试修复。 +3. Logback 迁移。 +4. fastjson2 迁移。 +5. 低风险依赖升级。 +6. 新增 `cat-boot` 过渡启动模块。 +7. Docker 从外置 Tomcat 切换为 `java -jar`。 +8. 升级计划文档和验证记录。 + +## 当前结论 + +当前推荐方案已经进入可继续验证状态:JDK 21 构建、Logback、fastjson2、低风险依赖和 `cat-boot` 可执行 JAR 已完成初步升级。接下来重点不是继续扩大版本升级范围,而是完成 Docker/MySQL/JSP/路由/上报链路的端到端验证,并把 Jakarta 迁移作为后续独立阶段处理。 diff --git a/SPRING_CONTEXT_MIGRATION_HANDOFF_2026-06-07.md b/SPRING_CONTEXT_MIGRATION_HANDOFF_2026-06-07.md new file mode 100644 index 0000000000..1eb3feb028 --- /dev/null +++ b/SPRING_CONTEXT_MIGRATION_HANDOFF_2026-06-07.md @@ -0,0 +1,910 @@ +# CAT Spring 上下文迁移交接文档(2026-06-07) + +## 1. 文档目的 + +这份文档用于下一次任务开始时快速恢复上下文。下一次继续迁移前,优先阅读本文,再结合当前 `git status --short` 和最近编译结果判断从哪一步继续。 + +当前项目路径: + +```text +D:\workspace\cat +``` + +当前总体目标: + +```text +逐步废弃 Plexus / Unidal Lookup / Unidal DAL 运行时依赖,让应用上下文、数据访问、Service、Manager、后台任务和 Web 层逐步迁移到 Spring 体系。 +``` + +当前迁移策略: + +1. 不一次性删除 Plexus。 +2. 先把 DAO / Repository / 配置 Manager / 基础 Service 接入 Spring。 +3. 旧 Unidal MVC Handler 暂时保留,由 Handler 通过桥接方式使用 Spring Bean。 +4. 每一步完成后都编译、打包、启动验证。 +5. 不确定运行结果时,停下来让用户在 IDEA 或本地环境验证。 + +## 2. 当前可运行状态 + +### 2.1 最新进度快照(本节优先) + +截至 2026-06-07 最近一轮迁移,配置页 Processor 的 Spring 依赖刷新和一批配置 Manager 的 Spring 注册已经完成,并通过编译、打包、临时启动和多条配置页 URL 验证。 + +本节是最新状态摘要;如果后文旧计划与本节冲突,以本节为准。 + +已完成的最新迁移点: + +1. `CatHomeSpringConfiguration` 继续扩展,新增注册了 `ConfigHtmlParser`、`RouterConfigManager`、`DomainGroupConfigManager`、`StorageGroupConfigManager`、`TopologyGraphConfigManager`、`TopoGraphFormatConfigManager`、`HeartbeatDisplayPolicyManager`、`ExceptionRuleConfigManager`、`AlertConfigManager`、`AlertPolicyManager`、`BaseRuleHelper`、`TransactionRuleConfigManager`、`EventRuleConfigManager`、`HeartbeatRuleConfigManager`。 +2. 多个配置 Manager 已补 setter,使 Spring 初始化不再依赖 `CatSpringContext` 在 `context.refresh()` 过程中已经可用。 +3. 配置页 Processor 已增加执行前刷新 Spring 依赖的逻辑,但 Processor 本体仍由 Plexus 创建。 +4. `TimerSyncTask.register` 已按 handler name 去重,避免 Plexus 和 Spring 双实例初始化时重复注册同名同步 handler。 +5. 最新一次启动日志显示 Spring Home 侧 `beanCount=90`。 + +当前工作树中,本轮迁移相关 Java 文件仍处于未提交修改状态。不要回滚这些改动,下一次继续前先用 `git status --short` 确认: + +```text +cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertConfigManager.java +cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertPolicyManager.java +cat-core/src/main/java/com/dianping/cat/task/TimerSyncTask.java +cat-home/src/main/java/com/dianping/cat/home/spring/CatHomeSpringConfiguration.java +cat-home/src/main/java/com/dianping/cat/report/alert/exception/ExceptionRuleConfigManager.java +cat-home/src/main/java/com/dianping/cat/report/alert/spi/config/BaseRuleConfigManager.java +cat-home/src/main/java/com/dianping/cat/report/page/DomainGroupConfigManager.java +cat-home/src/main/java/com/dianping/cat/report/page/dependency/config/TopoGraphFormatConfigManager.java +cat-home/src/main/java/com/dianping/cat/report/page/dependency/graph/TopologyGraphConfigManager.java +cat-home/src/main/java/com/dianping/cat/report/page/heartbeat/config/HeartbeatDisplayPolicyManager.java +cat-home/src/main/java/com/dianping/cat/report/page/storage/config/StorageGroupConfigManager.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/AlertConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/BaseProcesser.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/DependencyConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/EventConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/ExceptionConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/GlobalConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/HeartbeatConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/StorageConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/TransactionConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/router/config/RouterConfigManager.java +``` + +截至本交接文档编写时,用户已经多次确认项目可以正常启动和访问,最近一次用户反馈是: + +```text +已验证 ok / 没问题,继续。 +``` + +已知当前运行形态: + +1. JDK 已升级到 21。 +2. 项目通过 `cat-boot` 以可执行 JAR 启动。 +3. `cat-boot` 内嵌 Tomcat,部署 `cat-home.war` 到 `/cat`。 +4. 外置 Tomcat 已废弃。 +5. Logback 已替换旧日志实现。 +6. JSON 依赖已迁移到 fastjson2。 +7. Lombok 已引入。 +8. MyBatis 已覆盖 `CatApplication.sql` 中的表,并已有大量 Repository 迁移。 +9. Spring 上下文已建立,并能被旧 Plexus 对象通过 `CatSpringContext` 桥接访问。 + +常用启动参数: + +```text +-Dcat.home=C:\Users\Shang\.cat +-Dcat.log.path=C:\Users\Shang\.cat\logs +``` + +常用访问入口: + +```text +http://127.0.0.1:8080/cat +http://127.0.0.1:8080/cat/r +http://127.0.0.1:8080/cat/s/config +http://127.0.0.1:8080/cat/s/router?op=json&domain=cat&ip=127.0.0.1 +``` + +临时验证启动建议使用非默认端口,避免和用户 IDEA 启动实例冲突: + +```powershell +java -Dserver.port=18080 -Dcat.tcp.port=12280 -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +自己启动的 Java 进程验证完成后必须停止。 + +## 3. 今天左右已经完成的主要改动 + +### 3.1 JDK 21 和 Spring Boot 启动外壳 + +已完成: + +1. 根 POM 和模块 POM 已适配 JDK 21。 +2. 新增 `cat-boot` 模块。 +3. `CatBootApplication` 已作为 Spring Boot 启动入口。 +4. `cat-boot` 打包时包含并部署 `cat-home.war`。 +5. 默认系统参数已补齐: + +```text +cat.home=C:\Users\Shang\.cat +cat.log.path=C:\Users\Shang\.cat\logs +``` + +相关重点文件: + +```text +cat-boot/src/main/java/com/dianping/cat/boot/CatBootApplication.java +cat-boot/src/main/java/com/dianping/cat/boot/config/ +``` + +### 3.2 日志迁移 + +已完成: + +1. 日志实现切换为 Logback。 +2. 引入新版 Logback。 +3. 增加 `logback.xml`。 +4. 参考 `D:\workspace\lawyer-system` 的风格补充了日志文件输出配置。 +5. 处理过错误日志没有落入 `error.log` 的问题。 + +日志目录期望位置: + +```text +C:\Users\Shang\.cat\logs +``` + +注意: + +1. 控制台仍可能出现 CAT 客户端连接自身服务端的 WARN。 +2. Logback scan 相关 “Missing watchable .xml” 警告可以暂时忽略。 +3. 是否进入 `error.log` 取决于 logger、appender 和 level 配置,后续继续改日志时要实际触发 ERROR 验证。 + +### 3.3 fastjson2 和 Lombok + +已完成: + +1. JSON 依赖迁移为 fastjson2。 +2. 项目中直接 `com.alibaba.fastjson.*` import 已检查并处理。 +3. Lombok 已引入依赖和编译配置。 + +### 3.4 MyBatis DAO / Repository 迁移 + +已完成: + +1. 基于 `CatApplication.sql` 为所有表生成 MyBatis DO / Mapper / XML。 +2. `config` 表迁移为独立 MyBatis DAO,不再继承旧 DAO。 +3. `dailyreport` 表迁移到 MyBatis。 +4. 后续已扩展到所有表。 +5. 新 DAO 包和命名已按用户要求调整,例如 `ConfigMapper`、`ConfigDO`。 +6. 目标是新 DAO 层不依赖旧框架。 + +当前重要结构: + +```text +cat-core/src/main/java/com/dianping/cat/core/mybatis/ +cat-core/src/main/resources/mybatis/mapper/ +cat-home/src/main/resources/mybatis/mapper/ +cat-alarm/src/main/resources/mybatis/mapper/ +``` + +已知语义: + +1. `hostinfo` 表为空是正常场景,不应被当作错误。 +2. 查询不到数据时要尽量保持旧语义,例如该抛 `DalNotFoundException` 的地方不能被统一包装成普通 `DalException`。 + +### 3.5 Spring 上下文基础设施 + +已完成: + +1. 新增 Spring 上下文桥接类: + +```text +cat-core/src/main/java/com/dianping/cat/spring/CatSpringContext.java +``` + +2. 新增 Spring Home 配置: + +```text +cat-home/src/main/java/com/dianping/cat/home/spring/CatHomeSpringConfiguration.java +``` + +3. `CatSpringContext` 支持旧对象通过类型获取 Spring Bean: + +```java +CatSpringContext.getBeanIfAvailable(SomeClass.class) +``` + +4. `CatHomeSpringConfiguration` 已注册: + +```text +DataSource +SqlSessionFactory +SqlSessionTemplate +TransactionManager +TransactionTemplate +ConfigRepository +ProjectRepository +HostinfoRepository +各类 Report Repository +各类告警/配置相关 Repository +ProjectService +BusinessConfigManager +ServerConfigManager +SampleConfigManager +ServerFilterConfigManager +ReportReloadConfigManager +AtomicMessageConfigManager +TpValueStatisticConfigManager +AlertSummaryService +UserDefinedRuleManager +BaselineService +RemoteServersManager +DomainValidator +ServerStatisticManager +ConfigHtmlParser +RouterConfigManager +DomainGroupConfigManager +StorageGroupConfigManager +TopologyGraphConfigManager +TopoGraphFormatConfigManager +HeartbeatDisplayPolicyManager +ExceptionRuleConfigManager +AlertConfigManager +AlertPolicyManager +BaseRuleHelper +TransactionRuleConfigManager +EventRuleConfigManager +HeartbeatRuleConfigManager +``` + +最近一次启动验证看到 Spring Home 侧 Bean 数量约为: + +```text +beanCount=90 +``` + +### 3.6 Repository 和 Service 桥接 + +已完成并验证的桥接点包括: + +```text +AbstractReportService +TaskManager +DefaultTaskConsumer +system/page/config/Handler 的 ConfigModificationRepository +AlertSummaryService +UserDefinedRuleManager +BaseRuleConfigManager +RelatedSummaryBuilder +BusinessBaselineReportBuilder +AbstractGraphCreator +``` + +已注册或桥接的 Repository / Service 包括: + +```text +AlertRepository +AlterationRepository +BaselineRepository +TopologyGraphRepository +TaskRepository +AlertSummaryRepository +ConfigModificationRepository +MetricGraphRepository +MetricScreenRepository +ServerAlarmRuleRepository +UserDefineRuleRepository +AlertSummaryService +UserDefinedRuleManager +BaselineService(DefaultBaselineService) +``` + +这些改动的核心思路: + +```text +旧对象仍由 Plexus 创建,但运行前优先从 Spring 上下文刷新已迁移 Bean。 +``` + +这样可以避免一次性让 Spring 接管所有旧组件造成双容器初始化或字段注入为空。 + +## 4. 最近已经验证过的命令 + +常用编译验证: + +```powershell +mvn -pl cat-home -am compile -DskipTests +``` + +常用打包验证: + +```powershell +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +常用临时启动验证: + +```powershell +java -Dserver.port=18080 -Dcat.tcp.port=12280 -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +常用 HTTP 验证: + +```text +http://127.0.0.1:18080/cat +http://127.0.0.1:18080/cat/r +http://127.0.0.1:18080/cat/s/config +http://127.0.0.1:18080/cat/s/router?op=json&domain=cat&ip=127.0.0.1 +``` + +最近一轮已经额外验证过的配置页和路由入口: + +```text +http://127.0.0.1:18080/cat/s/config?op=routerConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=domainGroupConfigs +http://127.0.0.1:18080/cat/s/config?op=storageGroupConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=serverConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=sampleConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=topologyGraphNodeConfigList +http://127.0.0.1:18080/cat/s/config?op=topologyGraphEdgeConfigList +http://127.0.0.1:18080/cat/s/config?op=topoGraphFormatConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=heartbeatDisplayPolicy +http://127.0.0.1:18080/cat/s/config?op=heartbeatRuleConfigList +http://127.0.0.1:18080/cat/s/config?op=exception +http://127.0.0.1:18080/cat/s/config?op=alertPolicy +http://127.0.0.1:18080/cat/s/config?op=alertDefaultReceivers +http://127.0.0.1:18080/cat/s/config?op=transactionRule +http://127.0.0.1:18080/cat/s/config?op=eventRule +http://127.0.0.1:18080/cat/s/router?op=json&domain=cat&ip=127.0.0.1 +``` + +可暂时忽略的日志: + +```text +Unable to connect to CAT server /127.0.0.1:2280 +请求 http://127.0.0.1:8080/cat/s/router?... 失败 +Logback Missing watchable .xml... +``` + +端口注意: + +1. 默认 TCP 接收端口是 `2280`。 +2. 如果出现 `Address already in use: bind`,优先确认是否已有 CAT 实例或其他进程占用。 +3. 临时验证用 `-Dcat.tcp.port=12280` 可以绕开默认端口冲突。 + +## 5. 当前正在推进但尚未完成的工作 + +最新状态: + +```text +配置页 Processor Spring 依赖刷新已经完成并验证。 +``` + +本节下面保留的是迁移背景和当时的推进思路。下一次继续时不要再把“补 ConfigHtmlParser Spring Bean”或“给 Processor 增加 refreshSpringBeans()”当作未完成任务;这些已经完成。真正的下一步见文末“最新下一步计划”。 + +当前最近一轮准备推进的是: + +```text +配置页 Processor Spring 化。 +``` + +目标不是马上删除 Plexus 注册,而是让配置页 Processor 在执行前刷新 Spring 已迁移依赖。 + +涉及文件: + +```text +cat-home/src/main/java/com/dianping/cat/system/page/config/Handler.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/BaseProcesser.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/GlobalConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/AlertConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/DependencyConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/HeartbeatConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/ExceptionConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/TransactionConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/EventConfigProcessor.java +cat-home/src/main/java/com/dianping/cat/system/page/config/processor/StorageConfigProcessor.java +``` + +已经确认的现状: + +1. `Handler` 已有 `refreshSpringBeans()`,当前主要刷新 `ConfigModificationRepository`。 +2. `GlobalConfigProcessor` 已有 `refreshSpringBeans()`,当前刷新了: + +```text +ProjectService +SampleConfigManager +ServerConfigManager +ServerFilterConfigManager +ReportReloadConfigManager +``` + +3. `GlobalConfigProcessor` 还可以继续刷新但尚未补齐的依赖: + +```text +RouterConfigManager +DomainGroupConfigManager +StorageGroupConfigManager +``` + +这些 Manager 自身已具备 `refreshSpringBeans()` 能力,后续可考虑注册为 Spring Bean 或继续通过旧对象内部刷新。 + +4. `AlertConfigProcessor` 依赖: + +```text +AlertConfigManager +AlertPolicyManager +ConfigHtmlParser +``` + +这几个暂时不建议直接让 Spring 新建 Processor 后替换旧 Processor,除非先把所有字段依赖补齐。 + +5. `DependencyConfigProcessor` 依赖: + +```text +GlobalConfigProcessor +TopologyGraphConfigManager +TopoGraphFormatConfigManager +ConfigHtmlParser +``` + +`TopologyGraphConfigManager` 和 `TopoGraphFormatConfigManager` 已经有内部 Spring 刷新 `ConfigRepository` / `ContentFetcher` 的逻辑。 + +6. `HeartbeatConfigProcessor` 依赖: + +```text +HeartbeatRuleConfigManager +HeartbeatDisplayPolicyManager +ConfigHtmlParser +``` + +`HeartbeatDisplayPolicyManager` 已经有内部 Spring 刷新逻辑;`HeartbeatRuleConfigManager` 继承 `BaseRuleConfigManager`,已能刷新 `ConfigRepository`、`ContentFetcher`、`UserDefinedRuleManager`。 + +7. `ExceptionConfigProcessor` 依赖: + +```text +GlobalConfigProcessor +ExceptionRuleConfigManager +``` + +`ExceptionRuleConfigManager` 已有内部 Spring 刷新逻辑。 + +8. `TransactionConfigProcessor` 和 `EventConfigProcessor` 依赖: + +```text +TransactionRuleConfigManager +EventRuleConfigManager +RuleFTLDecorator(来自 BaseProcesser) +``` + +这两个 RuleConfigManager 继承 `BaseRuleConfigManager`,已能刷新部分 Spring 依赖。`RuleFTLDecorator` 暂时不建议急着 Spring 化,因为涉及模板装饰器和旧 components 配置。 + +9. `StorageConfigProcessor` 当前基本是空操作,风险较低。 + +## 6. 配置 Processor 迁移的推荐下一步 + +注意:本节是配置 Processor 迁移前写下的推荐顺序,其中 6.2 和 6.3 已经执行完成。下一次继续请以文末“最新下一步计划”为准。 + +下一次建议按下面顺序执行。 + +### 6.1 不直接切换为 Spring 新建 Processor + +不要马上在 `CatHomeSpringConfiguration` 中注册 8 个 Processor 并让 Handler 使用 Spring Bean。 + +原因: + +1. 当前 Processor 仍依赖大量 `@Inject` 字段。 +2. 如果 Spring `new Processor()`,这些 Plexus 字段不会自动注入。 +3. 直接替换会导致运行时 NPE,尤其是 `ConfigHtmlParser`、`RuleFTLDecorator`、各类 ConfigManager。 + +推荐策略: + +```text +Processor 仍由 Plexus 创建;Processor 执行前主动刷新 Spring 已迁移依赖。 +``` + +### 6.2 先补 `ConfigHtmlParser` Spring Bean + +`ConfigHtmlParser` 是无状态工具类,可以低风险注册到 Spring。 + +建议在: + +```text +cat-home/src/main/java/com/dianping/cat/home/spring/CatHomeSpringConfiguration.java +``` + +增加: + +```java +@Bean +public ConfigHtmlParser configHtmlParser() { + return new ConfigHtmlParser(); +} +``` + +### 6.3 给 Processor 增加 `refreshSpringBeans()` + +建议补充: + +1. `BaseProcesser.refreshSpringBeans()`: + +```text +可先不刷新 RuleFTLDecorator,避免模板相关风险。 +``` + +2. `GlobalConfigProcessor.refreshSpringBeans()` 继续补: + +```text +RouterConfigManager +DomainGroupConfigManager +StorageGroupConfigManager +ConfigHtmlParser +``` + +3. `AlertConfigProcessor.refreshSpringBeans()`: + +```text +ConfigHtmlParser +如果 AlertConfigManager / AlertPolicyManager 已注册 Spring,再刷新;否则保留 Plexus 注入。 +``` + +4. `DependencyConfigProcessor.refreshSpringBeans()`: + +```text +GlobalConfigProcessor +TopologyGraphConfigManager +TopoGraphFormatConfigManager +ConfigHtmlParser +``` + +这里要谨慎:如果 `GlobalConfigProcessor` 没有作为 Spring Bean 注册,就不要替换它;保留 Plexus 字段即可。 + +5. `HeartbeatConfigProcessor.refreshSpringBeans()`: + +```text +HeartbeatDisplayPolicyManager +ConfigHtmlParser +HeartbeatRuleConfigManager 如果已注册 Spring 再替换 +``` + +6. `ExceptionConfigProcessor.refreshSpringBeans()`: + +```text +ExceptionRuleConfigManager 如果已注册 Spring 再替换 +GlobalConfigProcessor 如果已注册 Spring 再替换 +``` + +7. `TransactionConfigProcessor` / `EventConfigProcessor`: + +```text +先只在 process() 开头调用 BaseProcesser.refreshSpringBeans() +是否替换 RuleConfigManager 等确认 Spring Bean 注册后再做 +``` + +### 6.4 Handler 只做刷新,不强切 Processor + +`Handler.refreshSpringBeans()` 下一步可以扩展成: + +```text +刷新 ConfigModificationRepository +必要时调用各 Processor 的 refreshSpringBeans() +``` + +但不建议直接: + +```java +m_globalConfigProcessor = CatSpringContext.getBeanIfAvailable(GlobalConfigProcessor.class); +``` + +除非该 Processor 的所有依赖都已经由 Spring 明确注入或手动 setter 完成。 + +## 7. 配置 Processor 迁移后的验证清单 + +完成上述小步后,至少执行: + +```powershell +mvn -pl cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +如果编译和打包通过,临时启动: + +```powershell +java -Dserver.port=18080 -Dcat.tcp.port=12280 -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +访问配置页: + +```text +http://127.0.0.1:18080/cat/s/config +http://127.0.0.1:18080/cat/s/config?op=serverConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=sampleConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=reportReloadConfigUpdate +http://127.0.0.1:18080/cat/s/config?op=alertPolicy +http://127.0.0.1:18080/cat/s/config?op=transactionRule +http://127.0.0.1:18080/cat/s/config?op=eventRule +http://127.0.0.1:18080/cat/s/config?op=heartbeatRuleConfigList +``` + +重点检查: + +1. 无 Processor 字段 NPE。 +2. 无 Mapper 未注册。 +3. 无 Spring Bean 循环依赖。 +4. 无重复初始化导致的任务重复启动。 +5. 配置页至少能返回页面或旧系统可接受的业务错误。 + +验证结束后停止自己启动的 Java 进程。 + +## 8. 后续总体计划 + +### 8.1 短期计划:继续扩大 Spring 桥接面 + +优先级从高到低: + +1. 配置 Processor 内部依赖刷新。 +2. 配置相关 Manager 注册或桥接到 Spring。 +3. 报表 Builder / Reloader / Task 继续桥接 Spring Repository 和 Service。 +4. 旧 Handler 逐步只保留请求分发和 JSP 渲染职责,业务依赖尽量来自 Spring。 + +### 8.2 中期计划:迁移后台任务 + +目标: + +```text +用 Spring 生命周期和调度机制替代 Plexus 初始化阶段启动任务。 +``` + +候选对象: + +```text +TimerSyncTask +ReportReloadTask +DefaultTaskConsumer +ProjectUpdateTask +CurrentReportBuilder +各类 ReportBuilder +各类 ReportReloader +CapacityUpdateStatusManager +DailyCapacityUpdater +HourlyCapacityUpdater +WeeklyCapacityUpdater +MonthlyCapacityUpdater +``` + +建议: + +1. 先加 Spring 调度基础设施。 +2. 每次只迁移一个任务族。 +3. 每个任务迁移后确认没有被 Plexus 和 Spring 重复启动。 +4. 任务迁移时一定要增加启动日志和停止逻辑。 + +### 8.3 长期计划:迁移 Web 层 + +最后再处理 Web 层,因为风险最大。 + +当前旧链路: + +```text +Unidal Web MVC -> Page Handler -> Payload -> Model -> JspViewer -> JSP +``` + +目标链路: + +```text +Spring MVC Controller -> Service -> ModelAndView / JSP +``` + +建议顺序: + +1. 先迁移低风险页面。 +2. 保持原 URL 尽量不变。 +3. 每迁移一个页面就验证一个页面。 +4. 等 DAO / Service / Manager / Task 基本 Spring 化之后,再删除 Unidal MVC。 + +## 9. 不要做的事 + +下一次继续时注意: + +1. 不要直接删除 `components.xml` 或 Plexus 注册。 +2. 不要一次性把 `com.dianping.cat` 全量加入 Spring 扫描。 +3. 不要让 Spring 和 Plexus 同时创建同一个会启动线程或注册定时任务的组件。 +4. 不要直接用 Spring 新建 Processor 替换旧 Processor,除非确认字段依赖全部补齐。 +5. 不要回滚用户已有改动。 +6. 不要长期保留自己启动的 Java 进程。 +7. 不要把空表、查无数据这类旧系统允许的场景误判成迁移失败。 + +## 10. 下一次任务开始建议执行的命令 + +先看工作树: + +```powershell +git status --short +``` + +查看旧容器依赖剩余面: + +```powershell +rg -n "ContainerLoader|getDefaultContainer|lookup\(" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +rg -n "org\.unidal\.lookup\.annotation|@Named|Initializable|LogEnabled|ContainerHolder" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +rg -n "DataSourceManager|MyBatisRepositorySupport" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +``` + +查看配置 Processor 当前状态: + +```powershell +rg -n "refreshSpringBeans|class .*ConfigProcessor|class BaseProcesser" cat-home/src/main/java/com/dianping/cat/system/page/config/processor cat-home/src/main/java/com/dianping/cat/system/page/config/Handler.java +``` + +然后以第 11 节的最新下一步计划为准继续推进。 + +## 11. 最新下一步计划(2026-06-07 更新) + +最终目标仍然是: + +```text +移除 Plexus / Unidal Lookup,使用 Spring 管理所有 Bean。 +``` + +当前已经完成到“配置页 Processor 执行前刷新 Spring 依赖 + 多个配置 Manager 注册为 Spring Bean”这一阶段。下一步不要急着删除 Plexus,也不要直接把 Handler 或 Processor 本体整体切到 Spring;应该继续扩大低风险 Bean 的 Spring 管理范围,并持续验证。 + +推荐下一步顺序: + +1. 先检查当前未提交改动和编译状态: + +```powershell +git status --short +mvn -pl cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +2. 继续挑选低风险 Manager 注册到 Spring,优先看业务规则和业务告警相关对象,例如: + +```text +BusinessRuleConfigManager +业务告警相关 ConfigManager / PolicyManager +只依赖 ConfigRepository、ContentFetcher、BaseRuleHelper、UserDefinedRuleManager 的 Manager +``` + +迁移方式沿用本轮做法: + +```text +先补 setter -> 在 CatHomeSpringConfiguration 注册 Bean -> Plexus 旧对象执行前 refreshSpringBeans() -> 编译/打包/启动/HTTP 验证。 +``` + +3. 暂缓把 `RuleFTLDecorator` 和配置 Processor 本体 Spring 化。`RuleFTLDecorator` 涉及模板装饰器和旧 components 注入,建议等更多 Manager 都稳定由 Spring 管理后再处理。 + +4. 后台任务迁移前先继续观察 `TimerSyncTask`。本轮已经给 `TimerSyncTask.register` 增加同名 handler 去重,但任务类后续 Spring 化时仍必须确认没有双容器重复启动。 + +5. 当配置 Manager 和后台任务基本稳定后,再迁移 Web 层: + +```text +Unidal Handler 暂时保留请求分发。 +等依赖都可从 Spring 获取后,再逐步用 Spring MVC Controller 替换低风险页面。 +``` + +最近一轮已通过的验证结果: + +```text +mvn -pl cat-home -am compile -DskipTests BUILD SUCCESS +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" BUILD SUCCESS +临时启动 cat-boot,端口 18080 / TCP 12280 OK +Spring Home beanCount 90 +多条 /cat/s/config 和 /cat/s/router URL HTTP 200 +``` + +可接受的已知日志: + +```text +Logback Missing watchable .xml +Maven shade overlap warnings +deprecated API warnings +``` + +不可忽略的日志: + +```text +NullPointerException +UnsatisfiedDependencyException +NoSuchBeanDefinitionException +Address already in use +同一个任务或 SyncHandler 重复启动导致的重复执行 +``` + +## 12. 最新进度快照(2026-06-13 更新) + +本节记录 2026-06-12 至 2026-06-13 的最新迁移进度。下次继续前,优先阅读本节,再结合 `git status --short` 判断工作区状态。 + +### 12.1 当前 Git 状态 + +截至本节更新时,工作区为干净状态: + +```powershell +git status --short +``` + +输出为空。上一批代码已经由用户提交。 + +### 12.2 已完成的最新迁移范围 + +围绕“最终移除 Plexus / Unidal Lookup / Unidal 相关依赖”的目标,最近一批已经完成并提交的改动包括: + +1. `cat-home/src/main/java/com/dianping/cat/report/page` 下的 `@Named` / `@Inject` 已清空。 +2. 报表页面服务层已迁移到显式组件注册,覆盖:`transaction`、`event`、`problem`、`heartbeat`、`storage`、`cross`、`matrix`、`state`、`top`、`business`、`metric baseline`。 +3. 多个 `ReportService` 子类已经从注解注册迁移为 configurator 中的显式字段依赖注册。 +4. 多个 `LocalModelService` 子类已经从注解注册迁移为显式组件注册,并补齐 `m_bucketManager`、`m_configManager`、`m_consumer`。 +5. historical model service 的隐式依赖已经改为显式字段名依赖:`m_reportService`、`m_configManager`。 +6. 已迁移 `business` 相关组件:`BusinessReportService`、`LocalBusinessService`、`BusinessPointParser`、`BusinessKeyHelper`。 +7. 已迁移 `metric baseline` 相关组件:`DefaultBaselineService`、`BaselineConfigManager`、`DefaultBaselineCreator`。 +8. 已迁移 `report/graph/svg`:`GraphBuilder`、`ValueTranslater`、`DefaultGraphBuilder`、`DefaultValueTranslater`。 +9. 已迁移 `DataExtractorImpl`,改为 `DataExtractor` 接口显式注册。 +10. 已清理 `report/task/reload` 组的 Unidal 注解:`ReportReloadTask`、`AbstractReportReloader` 和所有 `*ReportReloader` 实现。 + +`report/task/reload` 这一组已经由 `CatHomeSpringConfiguration` 通过 Spring Bean 和 setter 注入组装;生成的 `components.xml` 中没有对应 `ReportReloadTask` / `ReportReloader` 条目,因此只做注解清理,没有新增 Plexus 显式注册。 + +### 12.3 最近验证结果 + +最近一批迁移完成后,以下命令均已通过: + +```powershell +mvn -pl cat-home -am -DskipTests compile +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +验证过程中 Maven 仍会出现已知 warning,例如 deprecated API、shade overlapping resource、plexus plugin 执行时的 SLF4J no provider warning。这些 warning 暂时不是当前迁移阻塞项。 + +### 12.4 当前剩余注解范围 + +`cat-home/src/main/java/com/dianping/cat/report/page` 已经清空 Unidal lookup 注解。 + +`cat-home` 里剩余 `@Named` / `@Inject` 主要集中在: + +```text +cat-home/src/main/java/com/dianping/cat/report/alert +cat-home/src/main/java/com/dianping/cat/system/page +cat-home/src/main/java/com/dianping/cat/report/task +cat-home/src/main/java/com/dianping/cat/report/graph/metric/AbstractGraphCreator.java +cat-home/src/main/java/com/dianping/cat/CatHomeModule.java +``` + +跨模块仍然存在 Unidal 注解和容器依赖,主要在 `cat-core`、`cat-consumer`、`cat-alarm`、`cat-hadoop`。 + +因此现在还不能删除 Unidal / Plexus 依赖、`plexus-maven-plugin`、`codegen-maven-plugin` 或任何 `META-INF/plexus/components.xml`。 + +### 12.5 当前完成度评估 + +按最终目标“移除 Plexus / Unidal 相关依赖”估算,当前整体完成度约为: + +```text +35% - 45% +``` + +判断依据: + +1. 报表页面服务层这一条主线已经基本清理完成。 +2. Spring 手工配置和旧 MVC 兼容桥接已经比较稳定。 +3. 但 alert、system page、core/consumer/alarm/hadoop、Unidal Web MVC、Unidal DAL/codegen、Plexus 插件链路仍未完成。 +4. `components.xml` 仍然需要生成,旧容器仍是兼容运行链路的一部分。 + +### 12.6 推荐下一步计划 + +下一步建议继续迁移 `cat-home/report/alert`,但要拆小批次,不要一次性迁移全部 alert 链路。 + +推荐顺序: + +1. 先迁移低风险、已在 configurator 中注册或 Spring 中已有替代链路的 alert helper / manager。 +2. 再迁移 alert summary builder:`AlertSummaryExecutor`、`AlertSummaryService`、`RelatedSummaryBuilder`、`FailureSummaryBuilder`、`AlterationSummaryBuilder`、`AlertInfoBuilder`。 +3. 再迁移各类 alert domain:`business`、`transaction`、`event`、`heartbeat`、`exception`。 +4. 暂缓直接迁移 Web Handler、Unidal MVC、`RuleFTLDecorator` 等复杂链路。 + +每一小批迁移后至少执行: + +```powershell +mvn -pl cat-home -am -DskipTests compile +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +如果涉及 `components.xml` 生成,必须检查生成结果中是否包含预期 role、role-hint 和 field-name。 + +### 12.7 重要注意事项 + +1. 不要删除任何 `META-INF/plexus/components.xml`。 +2. 不要删除根 POM 或模块 POM 中的 Unidal / Plexus 依赖。 +3. 不要全量 Spring 扫描 `com.dianping.cat`。 +4. 不要让 Spring 和 Plexus 同时创建会启动线程、注册定时任务或注册 sync handler 的同一个组件。 +5. 迁移 descriptor 兼容组件时,优先使用显式 `field-name`,不要依赖注解扫描。 +6. 对 analyzer ID 相关 bean,避免 Spring bean 名和 analyzer ID 冲突,例如 `business`、`matrix`、`transaction` 等。 +7. 用户已经多次要求:如果验证没问题,可以继续后面的计划;但遇到需要运行时页面验证或业务决策的问题,应停下来让用户确认。 diff --git a/SPRING_CONTEXT_MIGRATION_PLAN.md b/SPRING_CONTEXT_MIGRATION_PLAN.md new file mode 100644 index 0000000000..2420222964 --- /dev/null +++ b/SPRING_CONTEXT_MIGRATION_PLAN.md @@ -0,0 +1,1389 @@ +# Spring 上下文迁移详细执行计划 + +## 1. 目标 + +将 CAT 当前由 Plexus/Unidal Lookup 管理的应用上下文,逐步迁移到 Spring 管理。最终状态是: + +1. 应用启动入口由 Spring Boot 管理。 +2. 基础设施 Bean、数据源、MyBatis、事务由 Spring 管理。 +3. DAO、Repository、Service、Manager、后台任务、Web Controller 由 Spring 创建和装配。 +4. 新代码不再依赖 Plexus、Unidal Lookup、Unidal DAL 生成运行时。 +5. 最终移除 `plexus-maven-plugin`、`META-INF/plexus/components.xml` 生成链路、旧 Lookup 容器和旧 DAL 依赖。 + +本计划采用分阶段迁移,不做一次性大替换。原因是当前 Plexus/Unidal 不只是 IoC 容器,还承担了组件生命周期、MVC 请求链路、DAL 代码生成、后台任务启动、日志注入等职责。一次性替换会把数据访问、页面渲染、JSP、Filter、定时任务和组件初始化问题混在一起,风险过高。 + +推荐路线是:先让 Spring 接管边界清晰的基础设施和 DAO,再迁移 Service/Manager,随后迁移后台任务,最后处理 Web MVC 和旧容器清理。 + +## 2. 当前状态 + +已经完成的前置工作: + +1. 项目已升级到 JDK 21。 +2. 已新增 `cat-boot`,可以通过 Spring Boot 外壳启动内嵌 Tomcat。 +3. 日志组件已迁移到 Logback。 +4. JSON 组件已迁移到 fastjson2。 +5. 已引入 Lombok。 +6. `CatApplication.sql` 中的表已生成 MyBatis `DO`、`Mapper`、XML。 +7. 主要业务 DAO 已逐步切换到新的 MyBatis Repository 兼容层。 +8. 当前项目可以正常启动运行。 + +当前仍然依赖旧框架的关键点: + +1. `cat-core`、`cat-home`、`cat-alarm`、`cat-consumer` 中仍大量使用 `org.unidal.lookup.annotation.Named` 和 `org.unidal.lookup.annotation.Inject`。 +2. 当前扫描结果显示,主代码中旧 Lookup 注解相关命中约 1145 处。 +3. `ContainerLoader`、`getDefaultContainer()`、`lookup(...)` 运行时查找命中约 33 处。 +4. `DataSourceManager` 命中约 67 处。 +5. `Initializable`、`LogEnabled`、`ContainerHolder` 生命周期相关命中约 224 处。 +6. 新 MyBatis Repository 当前约 50 个,但多数仍继承 `MyBatisRepositorySupport`。 +7. `MyBatisRepositorySupport` 当前仍通过 Unidal `DataSourceManager` 创建 MyBatis `SqlSessionFactory`。 +8. Web 请求仍主要经过 Unidal Web MVC、旧 Handler、Payload、Model、JSP Viewer 链路。 + +这说明项目已经具备 Spring 化的基础,但旧容器仍然是主上下文。下一步应优先切断 DAO 基础设施对 Unidal 的依赖。 + +## 3. 总体原则 + +1. 每个阶段完成后都必须保持可编译、可打包、可启动。 +2. 每个阶段只迁移一个明确边界,避免 DAO、Service、Web、任务调度同时大改。 +3. 新增代码使用 Spring 标准方式:`@Configuration`、`@Bean`、`@Component`、`@Service`、`@Repository`、构造器注入、`@Transactional`。 +4. 新增 DAO/Repository 不再继承旧 DAO,也不依赖 Unidal DAL。 +5. 过渡期允许保留旧业务方法签名,例如 `DalException`、`DalNotFoundException`,用于降低调用方改动成本。 +6. `DalNotFoundException` 语义必须保持兼容。查询不到数据时不能被包装成普通 `DalException`,否则旧业务上层会误判为系统错误。 +7. Spring 和 Plexus 共存阶段必须明确组件归属。同一个组件不能同时由两个容器创建。 +8. 每迁移一类组件,就删除或停用对应的 Plexus role 注册,避免双容器重复初始化。 +9. 任何阶段发现运行时风险,都应回滚当前阶段,而不是跨阶段修补。 + +## 4. 目标架构 + +迁移完成后的目标链路: + +```text +Spring Boot + -> Spring ApplicationContext + -> DataSource / TransactionManager + -> MyBatis SqlSessionFactory / Mapper + -> Repository + -> Service / Manager + -> Scheduler / Background Task + -> Spring MVC Controller / Filter +``` + +旧链路逐步退场: + +```text +Plexus components.xml + -> Unidal Lookup + -> Unidal DAL DataSourceManager + -> Generated Dao + -> Unidal MVC Handler +``` + +## 5. 阶段 0:建立基线和保护网 + +### 目标 + +在正式迁移 Spring 上下文前,固定当前可运行状态,确保后续每一步都有可比较的基线。 + +### 执行步骤 + +1. 记录当前 Git 状态: + +```bash +git status --short +``` + +2. 执行基础编译: + +```bash +mvn -pl cat-core -am compile -DskipTests +mvn -pl cat-alarm,cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +3. 启动应用: + +```bash +java -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +4. 验证默认启动参数是否生效: + +```text +cat.home = C:\Users\Shang\.cat +cat.log.path = C:\Users\Shang\.cat\logs +``` + +5. 访问关键页面: + +```text +http://localhost:8080/cat +http://localhost:8080/cat/r +``` + +6. 记录启动日志中的关键错误和警告,作为后续对比基线。 + +### 验收标准 + +1. 项目可以编译。 +2. `cat-boot` 可以打包。 +3. 应用可以启动。 +4. 页面可以访问。 +5. 日志可以输出到控制台和文件。 + +### 回滚点 + +此阶段不改代码,只建立基线。 + +## 6. 阶段 1:建立 Spring 基础设施边界 + +### 目标 + +让 Spring 先管理基础设施 Bean,为后续替换 Plexus 提供入口。此阶段不替换 Unidal MVC,不改变页面请求链路。 + +### 涉及模块 + +1. `cat-boot` +2. `cat-core` + +### 执行步骤 + +1. 在 `cat-boot` 中建立 Spring 配置包: + +```text +com.dianping.cat.boot.config +com.dianping.cat.boot.mybatis +com.dianping.cat.boot.bridge +``` + +2. 明确 Spring 扫描范围: + +```java +@SpringBootApplication(scanBasePackages = { + "com.dianping.cat.boot" +}) +``` + +暂时不要全量扫描 `com.dianping.cat`,否则大量旧 `@Named` 组件可能被 Spring 误创建。 + +3. 新增 Spring 上下文桥接类: + +```text +SpringContextHolder +``` + +该类只用于过渡期。新增业务代码禁止通过静态 holder 获取 Bean。 + +4. 新增启动健康检查 Bean: + +```text +CatSpringStartupVerifier +``` + +检查内容: + +1. Spring `ApplicationContext` 已启动。 +2. 必要配置已加载。 +3. `cat.home` 和 `cat.log.path` 已初始化。 + +5. 保持 `EmbeddedCatServer` 仍按现有方式部署 `cat-home.war` 到 `/cat`。 + +### 验证方式 + +```bash +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +java -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +### 验收标准 + +1. Spring Boot 正常启动。 +2. 内嵌 Tomcat 正常启动。 +3. `/cat` 应用正常部署。 +4. 没有重复 Bean、循环依赖、全量扫描导致的初始化异常。 + +### 回滚点 + +删除新增 Spring 配置和桥接类即可,不影响现有 Plexus 链路。 + +## 7. 阶段 2:让 MyBatis 和数据源交给 Spring 管理 + +### 目标 + +切断新 MyBatis Repository 对 Unidal `DataSourceManager` 的依赖,让 `DataSource`、`SqlSessionFactory`、`SqlSessionTemplate`、事务全部由 Spring 管理。 + +这是最推荐优先执行的阶段,边界清晰、收益最大。 + +### 涉及模块 + +1. `cat-boot` +2. `cat-core` +3. `cat-home` +4. `cat-alarm` + +### 执行步骤 + +1. 新增 Spring 数据源配置: + +```text +com.dianping.cat.boot.mybatis.CatDataSourceConfiguration +``` + +短期策略: + +1. 优先复用当前 `datasources.xml` 或等价连接参数,降低配置变化。 +2. 用 Spring Bean 包装出标准 `javax.sql.DataSource`。 +3. 保持数据源名称 `cat` 的兼容语义。 + +中期策略: + +1. 将数据库配置迁移到 `application.yml` 或外部配置文件。 +2. 使用 Spring Boot 标准 `spring.datasource.*`。 +3. 使用 HikariCP 或 Spring Boot 默认连接池。 + +2. 新增 MyBatis 配置: + +```text +com.dianping.cat.boot.mybatis.CatMyBatisConfiguration +``` + +配置内容: + +1. `SqlSessionFactoryBean` +2. `SqlSessionTemplate` +3. `DataSourceTransactionManager` +4. `@MapperScan` +5. Mapper XML 路径加载 + +Mapper 扫描范围建议先限定在新包: + +```text +com.dianping.cat.core.mybatis.mapper +com.dianping.cat.home.mybatis.mapper +com.dianping.cat.alarm.mybatis.mapper +``` + +3. 改造 `MyBatisRepositorySupport`。 + +当前问题: + +1. 持有 Unidal `DataSourceManager`。 +2. 手工构造 `SqlSessionFactory`。 +3. Repository 自己管理 `SqlSession`。 + +目标状态: + +1. 不再引用 `DataSourceManager`。 +2. 不再手工构造 `SqlSessionFactory`。 +3. Repository 通过构造器注入 Mapper。 +4. 写操作交给 Spring 事务。 + +4. 先选择 3 个低风险 Repository 做试点: + +```text +ConfigRepository +DailyReportRepository +HostinfoRepository +``` + +试点原因: + +1. `config` 是系统启动时高频读取表,能尽早暴露问题。 +2. `dailyreport` 已经迁移过,适合验证报表类查询。 +3. `hostinfo` 当前数据可能为空,适合验证空数据语义。 + +5. 保持兼容方法签名。 + +短期保留: + +```text +DalException +DalNotFoundException +Readset +Updateset +``` + +但方法内部不再依赖 Unidal DAL 查询引擎。 + +6. 写操作增加事务边界: + +```java +@Transactional +``` + +7. 删除已迁移 Repository 的 Plexus 注册。 + +检查位置: + +```text +cat-core/src/main/java/com/dianping/cat/build/*DatabaseConfigurator.java +cat-home/src/main/java/com/dianping/cat/build/*DatabaseConfigurator.java +cat-alarm/src/main/java/com/dianping/cat/build/*DatabaseConfigurator.java +``` + +### 验证方式 + +编译验证: + +```bash +mvn -pl cat-core -am compile -DskipTests +mvn -pl cat-alarm,cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +运行验证: + +1. 启动应用。 +2. 访问配置页。 +3. 访问报表页。 +4. 检查启动阶段 `server-config` 查询。 +5. 检查 `hostinfo` 空表时是否符合旧行为。 + +重点日志: + +1. 不能出现 Mapper 未注册。 +2. 不能出现事务管理器缺失。 +3. 不能出现 `DataSourceManager` 初始化失败。 +4. 查询不到数据时不能误报 ERROR。 + +### 验收标准 + +1. 试点 Repository 不再依赖 `DataSourceManager`。 +2. 试点 Repository 由 Spring 管理。 +3. Mapper 由 Spring 创建。 +4. 查询不到数据仍按旧行为抛 `DalNotFoundException`。 +5. 页面访问和启动配置加载正常。 + +### 回滚点 + +保留旧 `MyBatisRepositorySupport` 实现作为回滚参考。若 Spring MyBatis 配置异常,只回滚试点 Repository 和 Spring MyBatis 配置,不影响其他旧 DAO。 + +## 8. 阶段 3:批量迁移全部 MyBatis Repository + +### 目标 + +将当前约 50 个 MyBatis Repository 全部交给 Spring 管理,移除 Repository 层对 Unidal `DataSourceManager` 和 Plexus 注册的依赖。 + +### 执行分组 + +建议按模块分组迁移。 + +第一组:`cat-core` 基础表。 + +```text +config +dailyreport +hourlyreport +weeklyreport +monthreport +hostinfo +project +task +business_config +``` + +第二组:`cat-home` 页面和配置表。 + +```text +alert_summary +alteration +baseline +config_modification +metric_graph +metric_screen +overload +topology_graph +``` + +第三组:`cat-alarm` 告警表。 + +```text +alert +server_alarm_rule +user_define_rule +``` + +第四组:报表内容表。 + +```text +daily_report_content +hourly_report_content +monthly_report_content +weekly_report_content +``` + +### 执行步骤 + +1. 每次迁移一个模块或一组表,不跨模块混改。 +2. Repository 增加 Spring stereotype: + +```java +@Repository +``` + +3. 使用构造器注入 Mapper。 +4. 删除 `extends MyBatisRepositorySupport`。 +5. 删除 `openSession()` 手动 session 管理。 +6. 删除对应 Plexus role 注册。 +7. 保持外部调用方法签名。 +8. 保持异常语义兼容。 + +### 验证方式 + +每迁移一组执行: + +```bash +mvn -pl cat-core -am compile -DskipTests +mvn -pl cat-home -am compile -DskipTests +mvn -pl cat-alarm -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +检查旧依赖残留: + +```bash +rg -n "extends MyBatisRepositorySupport|DataSourceManager" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java +rg -n "C\\(.*Repository\\.class\\).*DataSourceManager" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java +``` + +### 验收标准 + +1. 所有新 MyBatis Repository 不再继承 `MyBatisRepositorySupport`。 +2. Repository 层不再引用 `DataSourceManager`。 +3. Repository 层不再需要 Plexus 注册。 +4. 所有 Mapper 能由 Spring 注入。 +5. 常用页面和后台任务读写正常。 + +### 回滚点 + +按分组回滚。不要在一个提交中混合迁移全部 Repository。 + +## 9. 阶段 4:迁移配置类 Manager 和基础 Service + +### 目标 + +将配置管理类和基础业务服务从 Plexus 组件迁移为 Spring Bean。 + +### 优先迁移对象 + +第一批配置管理类: + +```text +ServerConfigManager +AlertConfigManager +SenderConfigManager +BusinessConfigManager +AtomicMessageConfigManager +TpValueStatisticConfigManager +``` + +第二批基础服务: + +```text +HostinfoService +ProjectService +TaskManager +ServerStatisticManager +``` + +### 执行步骤 + +1. 将 `@Named` 替换为 Spring 注解: + +```java +@Component +@Service +``` + +2. 将 `org.unidal.lookup.annotation.Inject` 替换为构造器注入。 +3. 将 `Initializable.initialize()` 替换为: + +```java +@PostConstruct +``` + +或在需要明确启动顺序时使用: + +```java +SmartLifecycle +ApplicationRunner +``` + +4. 将 `LogEnabled` 替换为 SLF4J: + +```java +private static final Logger LOGGER = LoggerFactory.getLogger(CurrentClass.class); +``` + +5. 删除对应 Plexus role 注册。 +6. 对仍由 Plexus 创建、但需要访问 Spring Bean 的旧组件,短期使用桥接适配器。 +7. 避免新代码继续调用 `ContainerLoader.getDefaultContainer()`。 + +### 验证方式 + +```bash +mvn -pl cat-core -am compile -DskipTests +mvn -pl cat-alarm,cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +运行验证: + +1. 启动应用。 +2. 检查 `server-config` 加载。 +3. 修改配置后确认保存和读取正常。 +4. 检查配置刷新任务是否正常。 +5. 检查日志中没有重复初始化。 + +### 验收标准 + +1. 已迁移 Manager/Service 不再使用 Unidal `@Named`。 +2. 已迁移 Manager/Service 不再使用 Unidal `@Inject`。 +3. 已迁移 Manager/Service 不再依赖 `Initializable` 和 `LogEnabled`。 +4. 对应 Plexus role 已删除。 +5. 启动和配置读取行为保持兼容。 + +### 回滚点 + +按类回滚。配置管理类不要一次性全量迁移。 + +## 10. 阶段 5:迁移报表 Service 和业务 Manager + +### 目标 + +将报表查询、报表聚合、页面服务类从 Plexus 迁移到 Spring。 + +### 迁移对象 + +优先迁移服务类,而不是页面 Handler: + +```text +LocalTransactionService +HistoricalTransactionService +TransactionReportService +LocalEventService +HistoricalEventService +EventReportService +LocalProblemService +HistoricalProblemService +ProblemReportService +LocalHeartbeatService +HistoricalHeartbeatService +HeartbeatReportService +``` + +随后迁移: + +```text +DefaultReportManager +AbstractReportService 子类 +BusinessReportService +DependencyReportService +StateReportService +StorageReportService +MatrixReportService +TopReportService +``` + +### 执行步骤 + +1. 每次选择一个报表域迁移,例如 transaction 或 event。 +2. 将该报表域 Service 改为 Spring Bean。 +3. 保持 Handler 暂时仍由旧 MVC 创建。 +4. 通过桥接方式让旧 Handler 获取 Spring Service。 +5. 验证页面结果后,再迁移下一个报表域。 + +### 验证页面 + +至少覆盖: + +```text +/cat/r/t +/cat/r/e +/cat/r/p +/cat/r/h +/cat/r/state +/cat/r/top +``` + +具体 URL 以当前路由为准。 + +### 验收标准 + +1. 已迁移报表 Service 由 Spring 创建。 +2. 旧 Handler 仍可正常调用这些 Service。 +3. 报表页面正常渲染。 +4. 查询历史报表和实时报表均正常。 + +### 回滚点 + +按报表域回滚。某个报表域失败,不影响其他报表域。 + +## 11. 阶段 6:迁移后台任务和调度 + +### 目标 + +用 Spring 生命周期和 Spring 调度机制管理后台任务,替代 Plexus 初始化期间启动任务的方式。 + +### 迁移对象 + +```text +TimerSyncTask +ReportReloadTask +DefaultTaskConsumer +ProjectUpdateTask +CurrentReportBuilder +各类 ReportBuilder +各类 ReportReloader +CapacityUpdateTask +``` + +### 执行步骤 + +1. 新增 Spring 调度配置: + +```java +@EnableScheduling +``` + +2. 配置统一线程池: + +```text +ThreadPoolTaskScheduler +``` + +3. 将手动启动线程替换为: + +```java +@Scheduled +SmartLifecycle +ApplicationRunner +``` + +4. 每个任务增加开关配置,支持临时关闭。 +5. 任务启动日志必须包含任务名称和调度周期。 +6. 应用关闭时任务必须优雅停止。 +7. 防止同一任务被 Plexus 和 Spring 重复启动。 + +### 验证方式 + +1. 启动应用,观察任务启动日志。 +2. 检查同一任务是否只启动一次。 +3. 触发报表 reload。 +4. 触发项目更新任务。 +5. 关闭应用,确认线程池正常退出。 + +### 验收标准 + +1. 已迁移任务由 Spring 生命周期管理。 +2. 任务不会重复启动。 +3. 应用关闭无挂起线程。 +4. 任务异常有统一日志。 + +### 回滚点 + +按任务回滚。先迁移低风险任务,再迁移核心报表生成任务。 + +## 12. 阶段 7:迁移 Web 层到 Spring MVC + +### 目标 + +用 Spring MVC 替换 Unidal Web MVC 请求生命周期。 + +这是风险最高、改动最大的阶段,应在 DAO、Service、Manager、任务基本迁移完成后再执行。 + +### 当前旧链路 + +```text +org.unidal.web.MVC +DefaultRequestLifecycle +Page Handler +Payload +Model +BaseJspViewer +JSP +``` + +### 迁移策略 + +优先采用页面级渐进迁移: + +1. 第一阶段:Spring Controller 包装旧 Handler。 +2. 第二阶段:逐个页面替换为 Spring MVC Controller。 +3. 第三阶段:替换 Payload/Model 绑定方式。 +4. 第四阶段:替换 JSP Viewer。 +5. 第五阶段:删除 Unidal MVC。 + +### 优先页面 + +先迁移低风险页面: + +```text +home +config +state +logview +``` + +再迁移核心报表页面: + +```text +transaction +event +problem +heartbeat +business +dependency +matrix +top +``` + +最后迁移告警和复杂配置页面: + +```text +alert +router config +overload +storage +statistics +``` + +### 执行步骤 + +1. 新增 Spring MVC 配置。 +2. 配置 JSP ViewResolver。 +3. 保持静态资源路径兼容。 +4. 迁移 Filter: + +```text +PermissionFilter +DomainFilter +CatFilter +``` + +5. 增加统一异常处理: + +```java +@ControllerAdvice +``` + +6. 逐个页面迁移 Controller。 +7. 保持原 URL 尽量不变。 +8. 每迁移一个页面就删除对应旧路由注册。 + +### 验证页面 + +至少覆盖: + +```text +http://localhost:8080/cat +http://localhost:8080/cat/r +http://localhost:8080/cat/r/t +http://localhost:8080/cat/r/e +http://localhost:8080/cat/r/p +配置页面 +告警页面 +报表历史查询页面 +``` + +### 验收标准 + +1. 页面可以访问。 +2. JSP 正常渲染。 +3. 静态资源正常加载。 +4. 权限、domain、跳转逻辑正常。 +5. 原有 URL 尽量兼容。 +6. 已迁移页面不再经过 Unidal MVC。 + +### 回滚点 + +按页面回滚。不要一次性替换全部 MVC。 + +## 13. 阶段 8:移除 Plexus/Unidal Lookup + +### 目标 + +彻底移除旧容器。 + +### 前置条件 + +必须同时满足: + +1. DAO 已全部由 Spring 管理。 +2. Repository 不再依赖 `DataSourceManager`。 +3. Service/Manager 已由 Spring 管理。 +4. 后台任务已由 Spring 管理。 +5. Web 层已迁移到 Spring MVC,或不再依赖 Unidal MVC 生命周期。 +6. 运行时代码不再调用 `ContainerLoader.getDefaultContainer()`。 +7. 构建不再需要生成 `components.xml`。 + +### 执行步骤 + +1. 删除 `plexus-maven-plugin`。 +2. 删除 `META-INF/plexus/components.xml` 生成流程。 +3. 删除旧组件注册类。 +4. 删除 `org.unidal.lookup` 运行时依赖。 +5. 删除 `ContainerHolder`、`ContainerLoader` 使用。 +6. 删除旧 DAL 生成流程: + +```text +codegen-maven-plugin dal-jdbc +Readset +Updateset +旧 *Dao +``` + +7. 清理 POM 依赖: + +```text +org.unidal.framework:dal-jdbc +org.unidal.framework:foundation-service +org.unidal.framework:web-framework +org.unidal.framework:test-framework +``` + +注意:只有当没有代码引用时才能删除。 + +### 验证方式 + +```bash +mvn clean package -DskipTests +mvn test +``` + +运行验证: + +1. 应用启动。 +2. 页面访问。 +3. 数据库读写。 +4. 客户端上报。 +5. 报表生成。 +6. 告警链路。 +7. 应用关闭。 + +### 验收标准 + +1. 依赖树中不再需要 Plexus/Unidal Lookup。 +2. 构建不再生成 `components.xml`。 +3. 运行时没有 Plexus 容器初始化日志。 +4. 核心功能仍可用。 + +### 回滚点 + +此阶段风险最高,只能在前面阶段全部完成并稳定后执行。建议单独提交,单独验证。 + +## 14. 每阶段通用检查清单 + +每完成一个阶段或一组类迁移,都执行以下检查。 + +### 编译和打包 + +```bash +mvn -pl cat-core -am compile -DskipTests +mvn -pl cat-alarm,cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +### 旧 DAO import 检查 + +```bash +rg -n "import com\.dianping\.cat\.(core\.dal|core\.config|home\.dal\.report|alarm)\.[A-Za-z0-9]+Dao;" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +``` + +### 旧容器查找检查 + +```bash +rg -n "ContainerLoader|getDefaultContainer|lookup\(" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +``` + +### Plexus 注解和生命周期检查 + +```bash +rg -n "org\.unidal\.lookup\.annotation|@Named|Initializable|LogEnabled|ContainerHolder" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +``` + +### 数据源旧依赖检查 + +```bash +rg -n "DataSourceManager|MyBatisRepositorySupport" cat-core/src/main/java cat-home/src/main/java cat-alarm/src/main/java cat-consumer/src/main/java +``` + +### 运行验证 + +1. 启动应用。 +2. 访问首页。 +3. 访问报表页。 +4. 访问配置页。 +5. 修改并保存一项配置。 +6. 检查日志文件。 +7. 检查控制台 ERROR。 +8. 正常停止应用。 + +## 15. 风险和应对 + +### 风险 1:双容器重复创建组件 + +表现: + +1. 初始化执行两次。 +2. 后台任务重复启动。 +3. 配置重复加载。 + +应对: + +1. Spring 扫描范围保持收敛。 +2. 每迁移一个组件就删除对应 Plexus role。 +3. 后台任务迁移时增加启动日志和唯一性检查。 + +### 风险 2:异常语义不兼容 + +表现: + +1. 查询不到数据被记录为 ERROR。 +2. 旧业务上层逻辑进入异常分支。 + +应对: + +1. `DalNotFoundException` 必须原样透传。 +2. Repository 不要统一包装所有异常。 +3. 为核心查询补充单元测试。 + +### 风险 3:事务边界变化 + +表现: + +1. 写操作未提交。 +2. 多表更新部分成功。 +3. 连接泄漏。 + +应对: + +1. 写操作统一加 `@Transactional`。 +2. Repository 不再手动管理 session。 +3. 用 Spring `DataSourceTransactionManager` 管理事务。 + +### 风险 4:启动顺序变化 + +表现: + +1. 配置还未加载,任务已启动。 +2. Web 页面访问时 Service 未初始化。 + +应对: + +1. 对关键 Bean 使用明确生命周期。 +2. 后台任务使用 `SmartLifecycle` 或 `ApplicationReadyEvent`。 +3. 不依赖字段注入的隐式顺序。 + +### 风险 5:Web 层迁移破坏 URL 和 JSP + +表现: + +1. 原 URL 404。 +2. JSP tag 或静态资源缺失。 +3. 权限过滤逻辑失效。 + +应对: + +1. Web 层最后迁移。 +2. 按页面迁移。 +3. 保留原 URL。 +4. 每个页面迁移后单独验收。 + +## 16. 推荐下一步 + +建议下一步从阶段 2 开始,先做一个最小可验证闭环: + +1. 新增 Spring `DataSource`、`SqlSessionFactory`、`SqlSessionTemplate`、`TransactionManager` 配置。 +2. 只迁移 `ConfigRepository`、`DailyReportRepository`、`HostinfoRepository` 三个 Repository。 +3. 保持旧方法签名和异常语义。 +4. 删除这三个 Repository 对 `DataSourceManager` 的依赖。 +5. 启动应用验证 `server-config`、报表查询、空 `hostinfo` 表行为。 +6. 通过后再批量迁移其他 Repository。 + +这个顺序收益最大,因为它先把 DAO 基础设施从 Unidal 中解耦出来,同时不会立即触碰最高风险的 Web MVC 链路。 + +## 17. 2026-06-09 当前结论与下一步计划 + +### 当前代码基线 + +用户已提交上一轮日志补充和 Spring 迁移相关代码。以 2026-06-09 当前工作树为新基线,`git status --short` 为空。 + +当前项目仍不能直接删除 Plexus / Unidal 依赖。原因是旧框架仍承担三类核心职责: + +1. 组件容器和运行时查找:仍有约 27 个生产 Java 文件使用 `ContainerHolder`、`lookup(...)`、`lookupMap(...)`。 +2. Unidal Web MVC:`cat-home` 中约 146 个生产 Java 文件仍涉及 `org.unidal.web`、`PageHandler`、`ActionPayload`、`ViewModel`、`BaseJspViewer`、`FieldMeta` 等。 +3. Unidal DAL / codegen:约 154 个生产 Java 文件仍涉及 `org.unidal.dal`、`DalException`、`DalNotFoundException` 或生成 DAO / model。 + +根 `pom.xml` 中仍存在以下关键依赖或插件管理项: + +```text +org.unidal.framework:dal-jdbc +org.unidal.framework:foundation-service +org.unidal.framework:web-framework +org.unidal.framework:test-framework +org.unidal.webres:WebResServer +org.unidal.maven.plugins:codegen-maven-plugin +org.unidal.maven.plugins:plexus-maven-plugin +``` + +源码资源中仍存在 Plexus 组件描述文件: + +```text +cat-alarm/src/main/resources/META-INF/plexus/components.xml +cat-consumer/src/main/resources/META-INF/plexus/components.xml +cat-core/src/main/resources/META-INF/plexus/components.xml +cat-hadoop/src/main/resources/META-INF/plexus/components.xml +cat-home/src/main/resources/META-INF/plexus/components.xml +``` + +这些文件暂时不能提前删除,必须等对应 Spring 替代链路验证通过后再分批移除。 + +### 已存在的迁移桥接基础 + +当前已经具备继续迁移的 Spring 桥接基础: + +1. `cat-home/src/main/java/com/dianping/cat/home/spring/CatHomeSpringContextListener.java` 已创建 Spring `AnnotationConfigApplicationContext`,并将上下文写入 `ServletContext` 和 `CatSpringContext`。 +2. `cat-home/src/main/java/com/dianping/cat/home/spring/CatHomeSpringConfiguration.java` 已手动注册大量 Repository、ConfigManager、Service Bean。 +3. `cat-core/src/main/java/com/dianping/cat/spring/CatSpringContext.java` 已提供旧代码获取 Spring Bean 的过渡桥。 +4. `cat-boot/src/main/java/com/dianping/cat/boot/CatBootApplication.java` 已作为 Spring Boot 启动入口。 + +但当前 `cat-home/src/main/webapp/WEB-INF/web.xml` 仍将 `/r/*` 和 `/s/*` 交给 `org.unidal.web.MVC`,`CatServlet` 也仍依赖 `AbstractContainerServlet`、`DefaultModuleContext`、`ModuleInitializer`。因此 Web MVC 和启动模块初始化仍属于高风险区域,暂不作为下一步优先项。 + +### 迁移顺序调整 + +截至 2026-06-09,推荐迁移顺序调整为: + +1. 先替换组件容器和 `lookupMap(...)` 型扩展点。 +2. 再移除 Plexus 生命周期和日志接口,例如 `Initializable`、`LogEnabled`、`org.codehaus.plexus.logging.Logger`。 +3. 然后迁移 Unidal Web MVC。 +4. 再继续替换 Unidal DAL / codegen。 +5. 最后移除 `plexus-maven-plugin`、`codegen-maven-plugin`、`components.xml` 和根 POM 中的 Unidal 依赖。 + +此顺序的原因是:如果先迁移 Web MVC 或 DAL,会同时牵动 URL 路由、JSP、Filter、Repository、异常语义和启动流程;而 `lookupMap(...)` 型 Manager 边界较清晰,可以先通过 Spring `Map` / `List` 注入建立替代链路,并保留旧 Plexus fallback 作为回滚保护。 + +### 下一步执行项 + +下一步建议迁移第一组低风险 `lookupMap(...)` 管理器: + +```text +cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SenderManager.java +cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/DecoratorManager.java +cat-alarm/src/main/java/com/dianping/cat/alarm/spi/spliter/SpliterManager.java +``` + +执行方式: + +1. 为 Manager 增加 Spring 注入入口,例如 setter 或构造器注入。 +2. 优先使用 Spring 注入的 `Map`、`Map`、`Map`。 +3. 暂时保留原有 `lookupMap(...)` fallback,确保 Spring Bean 未完全注册时旧链路仍可运行。 +4. 在 `CatHomeSpringConfiguration` 中注册 Manager 及其扩展点 Bean。 +5. 增加必要的 `info` / `warn` 日志,明确当前使用的是 Spring 注入还是 Plexus fallback。 +6. 编译并启动验证告警相关初始化、配置页和常用 `/cat/r/*` 页面。 + +### 验证命令 + +```powershell +mvn -pl cat-alarm,cat-home -am compile -DskipTests +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +java -Dserver.port=18080 -Dcat.tcp.port=12280 -jar cat-boot\target\cat-boot-4.0-RC1.jar +``` + +建议验证 URL: + +```text +http://127.0.0.1:18080/cat +http://127.0.0.1:18080/cat/r +http://127.0.0.1:18080/cat/r/business +http://127.0.0.1:18080/cat/s/config +``` + +验收标准: + +1. 编译和打包通过。 +2. 应用能启动,且没有重复初始化同一 Manager。 +3. 告警 SPI Manager 能正常加载扩展点。 +4. 日志能看出 Spring 注入是否生效。 +5. 如果 Spring 注入缺失,应有明确 warn,并能回退到 Plexus `lookupMap(...)`。 +6. `/cat/r/business` 和配置页保持可访问。 + +### 暂缓事项 + +以下事项暂缓,不进入下一步改动: + +1. 暂不修复用户当前环境中没有复现的 `/cat/r/business` NPE。 +2. 暂不删除任何 `META-INF/plexus/components.xml`。 +3. 暂不移除根 POM 中的 Unidal / Plexus 依赖。 +4. 暂不迁移 `org.unidal.web.MVC`。 +5. 暂不批量替换所有 DAL / codegen 相关代码。 + +## 18. 2026-06-13 当前进度更新 + +### 已完成 + +最近一批迁移已经完成并提交,重点是把 `cat-home` 报表页面服务层从 Unidal lookup 注解迁移到显式注册: + +```text +cat-home/src/main/java/com/dianping/cat/report/page +``` + +该目录下当前已经没有 `@Named` / `@Inject` 残留。 + +已覆盖的报表域: + +```text +transaction +event +problem +heartbeat +storage +cross +matrix +state +top +business +metric baseline +``` + +同时已完成: + +```text +report/graph/svg -> GraphBuilder / ValueTranslater 显式注册 +report/graph/metric/impl/DataExtractorImpl -> DataExtractor 显式注册 +report/task/reload -> 清理 Unidal 注解,保留 Spring setter 注入路径 +``` + +### 验证结果 + +最近一批迁移后已通过: + +```powershell +mvn -pl cat-home -am -DskipTests compile +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +## 19. 终极目标:移除 Unidal / Plexus 相关依赖的后续路线 + +本节记录 2026-06-14 之后的后续操作计划。当前 `@Named` / `@Inject` lookup 注解已经基本清空,但项目距离彻底移除 Unidal / Plexus 依赖仍有明显距离。后续重点需要从“注解迁移”切换到“依赖拆解”。 + +### 19.1 当前依赖面分层 + +当前剩余依赖大致分为四层: + +1. 构建期依赖 + +```text +org.unidal.maven.plugins:codegen-maven-plugin +org.unidal.maven.plugins:plexus-maven-plugin +``` + +这两类插件仍负责生成 DAL model、DAL JDBC 代码,以及 `META-INF/plexus/components.xml`。在 DAL、MVC、运行时容器完全替换前,不应直接删除。 + +2. 运行时容器和 descriptor + +```text +META-INF/plexus/components.xml +org.unidal.lookup.* +org.codehaus.plexus.* +``` + +这部分仍承载旧容器的组件注册、`lookup(...)`、`lookupMap(...)`、生命周期初始化和 fallback 链路。当前不能一次性删除。 + +3. Web MVC 依赖 + +```text +org.unidal.web.mvc.* +org.unidal.web.MVC +BaseJspViewer +PageHandler +ActionContext +PayloadMeta / ModelMeta / FieldMeta +``` + +这部分影响 `/cat/r/*`、`/cat/s/*` 路由、页面 handler、payload、model、JSP viewer 和 servlet 初始化链路,属于高风险迁移项,应放在中后期。 + +4. 工具类 / 辅助类 / 测试基建 + +```text +org.unidal.helper.* +org.unidal.tuple.Pair +org.unidal.lookup.util.StringUtils +org.codehaus.plexus.util.StringUtils +org.unidal.lookup.ComponentTestCase +lookup(...) in tests +``` + +这部分风险相对低,适合作为下一阶段的入口,用小批量替换逐步缩小 Unidal 依赖面。 + +### 19.2 推荐拆除顺序 + +后续建议按以下顺序推进: + +1. 建立依赖清单和防回归检查。 +2. 替换低风险工具类和辅助类。 +3. 清理测试中的 `ComponentTestCase` / `lookup(...)`。 +4. 迁移剩余 `lookupMap(...)` 扩展点管理器。 +5. 替换或隔离 Unidal Web MVC。 +6. 替换或隔离 Unidal DAL / codegen。 +7. 移除 `plexus-maven-plugin` 和 `components.xml` 生成链路。 +8. 最后移除根 POM 中 Unidal / Plexus 相关依赖和仓库配置。 + +### 19.3 下一步具体执行项 + +下一步不建议直接删除 POM 依赖,而是先做“依赖清单 + 第一批低风险替换”。 + +执行项如下: + +1. 生成按模块统计的源码引用清单: + +```powershell +rg -n "org\.unidal\.lookup|org\.unidal\.web\.mvc|org\.unidal\.dal\.jdbc|org\.unidal\.helper|org\.unidal\.tuple|org\.codehaus\.plexus" --glob "**/src/**/*.{java,scala,xml}" . +``` + +输出需要按模块分组,区分: + +```text +cat-client +cat-core +cat-consumer +cat-hadoop +cat-alarm +cat-home +cat-boot +integration +``` + +2. 先替换低风险工具类: + +```text +org.codehaus.plexus.util.StringUtils +org.unidal.lookup.util.StringUtils +org.unidal.tuple.Pair +org.unidal.helper.Files +org.unidal.helper.Splitters +org.unidal.helper.Urls +``` + +替换原则: + +```text +StringUtils -> JDK / Spring / Apache Commons Lang 中已存在能力 +Pair -> Java record / Map.Entry / Spring Pair / 局部小对象 +Files -> java.nio.file.Files +Urls -> java.net.URI / URL / URLEncoder / UriComponentsBuilder +Splitters -> JDK String split / Pattern / Stream +``` + +每一批只替换一个工具类族,避免同时改动业务语义和依赖边界。 + +3. 优先选择不影响启动链路的目录: + +```text +cat-home/src/main/java/com/dianping/cat/report/page/*/transform +cat-home/src/main/java/com/dianping/cat/report/page/*/graph +cat-home/src/main/java/com/dianping/cat/report/page/*/display +cat-consumer/src/test/java +cat-core/src/test/java +``` + +暂缓目录: + +```text +cat-home/src/main/java/com/dianping/cat/*/Handler.java +cat-home/src/main/java/com/dianping/cat/*/Payload.java +cat-home/src/main/java/com/dianping/cat/*/Model.java +cat-home/src/main/java/com/dianping/cat/*/JspViewer.java +CatServlet / CatHomeModule / Web MVC 初始化链路 +DAL repository / DAO / codegen 生成类 +``` + +4. 替换后执行精确扫描: + +```powershell +rg -n "org\.unidal\.lookup\.util\.StringUtils|org\.codehaus\.plexus\.util\.StringUtils|org\.unidal\.tuple\.Pair|org\.unidal\.helper\.(Files|Splitters|Urls)" --glob "**/src/**/*.{java,scala}" . +``` + +5. 执行 Maven 验证: + +```powershell +mvn validate +mvn -pl cat-home -am -DskipTests compile +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` + +如果只改测试代码,则至少执行: + +```powershell +mvn -pl cat-consumer,cat-home -am -DskipTests test-compile +``` + +### 19.4 暂时不要做的事 + +在完成工具类、测试基建、`lookupMap(...)` 和 Web MVC 替换前,暂时不要执行以下操作: + +1. 不要删除根 POM 中的 `org.unidal.framework` 依赖。 +2. 不要删除 `org.unidal.maven.plugins:codegen-maven-plugin`。 +3. 不要删除 `org.unidal.maven.plugins:plexus-maven-plugin`。 +4. 不要删除任何 `META-INF/plexus/components.xml`。 +5. 不要全量替换 `org.unidal.web.mvc.*`。 +6. 不要一次性重写 DAL / DAO / Repository 层。 +7. 不要因为看到第三方 `@Inject` 就全局禁用 `@Inject`;当前只应禁止 `org.unidal.lookup.annotation.Inject` 和 `org.unidal.lookup.annotation.Named`。 + +### 19.5 当前已加入的防回归检查 + +已在父 `pom.xml` 中加入 validate 阶段检查,禁止源码重新引入: + +```text +import org.unidal.lookup.annotation.Inject; +import org.unidal.lookup.annotation.Named; +``` + +该检查不会误伤以下第三方注入: + +```text +org.elasticsearch.common.inject.Inject +javax.inject.Inject +``` + +后续可以逐步扩展防回归规则,但每次只能禁止已经完成替换并验证通过的依赖族。 + +### 当前阶段判断 + +项目仍然不能直接移除 Plexus / Unidal 依赖。当前大致完成度约为: + +```text +35% - 45% +``` + +主要剩余工作: + +```text +cat-home/report/alert +cat-home/system/page +cat-home/report/task +cat-core +cat-consumer +cat-alarm +cat-hadoop +Unidal Web MVC +Unidal DAL / codegen +Plexus components.xml 生成链路 +``` + +### 下一步推荐 + +下一步建议进入 `cat-home/report/alert` 的小批量迁移,优先迁移低风险 helper / manager / summary builder,不要直接迁移 Web Handler 或删除 `components.xml`。 + +推荐顺序: + +```text +1. Alert helper / config manager +2. Alert summary service / executor / builders +3. business / transaction / event / heartbeat / exception alert domain +4. 最后再考虑 system/page 和 Web MVC +``` + +每完成一小批后继续执行: + +```powershell +mvn -pl cat-home -am -DskipTests compile +mvn -pl cat-boot -am package -DskipTests "-Dmaven.javadoc.skip=true" +``` diff --git a/cat-alarm/pom.xml b/cat-alarm/pom.xml index 0d7c8058ce..5881e80bff 100644 --- a/cat-alarm/pom.xml +++ b/cat-alarm/pom.xml @@ -20,16 +20,12 @@ cat-core - org.unidal.framework - foundation-service + org.mybatis + mybatis - org.unidal.framework - web-framework - - - org.unidal.framework - dal-jdbc + org.projectlombok + lombok javax.servlet @@ -46,15 +42,14 @@ org.freemarker freemarker - - org.unidal.framework - test-framework - test - commons-lang commons-lang + + org.apache.commons + commons-lang3 + com.google.code.gson gson @@ -72,8 +67,8 @@ httpmime - com.alibaba - fastjson + com.alibaba.fastjson2 + fastjson2 junit @@ -81,57 +76,6 @@ test - - - - org.unidal.maven.plugins - codegen-maven-plugin - - - generate data model - generate-sources - - dal-model - - - ${basedir}/src/main/resources/META-INF/dal/model/server-alarm-rule-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/sender-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/alert-policy-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/alert-receiver-manifest.xml, - - - - - generate dal jdbc model - generate-sources - - dal-jdbc - - - ${basedir}/src/main/resources/META-INF/dal/jdbc/alarm-manifest.xml, - - - - - - org.unidal.maven.plugins - plexus-maven-plugin - - - generate plexus component descriptor - process-classes - - plexus - - - com.dianping.cat.build.ComponentsConfigurator - - - - - - utf-8 diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/Alert.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/Alert.java new file mode 100644 index 0000000000..23cfb03443 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/Alert.java @@ -0,0 +1,183 @@ +package com.dianping.cat.alarm; + + +public class Alert { + private long m_id; + + private String m_domain; + + private java.util.Date m_alertTime; + + private String m_category; + + private String m_type; + + private String m_content; + + private String m_metric; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private String[] m_categories; + public void afterLoad() { + m_keyId = m_id; + } + + public java.util.Date getAlertTime() { + return m_alertTime; + } + + public String[] getCategories() { + return m_categories; + } + + public String getCategory() { + return m_category; + } + + public String getContent() { + return m_content; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public String getMetric() { + return m_metric; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + public String getType() { + return m_type; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public Alert setAlertTime(java.util.Date alertTime) { + m_alertTime = alertTime; + return this; + } + + public Alert setCategories(String[] categories) { + m_categories = categories; + return this; + } + + public Alert setCategory(String category) { + m_category = category; + return this; + } + + public Alert setContent(String content) { + m_content = content; + return this; + } + + public Alert setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public Alert setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public Alert setDomain(String domain) { + m_domain = domain; + return this; + } + + public Alert setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public Alert setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public Alert setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public Alert setMetric(String metric) { + m_metric = metric; + return this; + } + + public Alert setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + + public Alert setType(String type) { + m_type = type; + return this; + } + + public Alert setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("Alert["); + sb.append("alert-time: ").append(m_alertTime); + sb.append(", categories: ").append(m_categories == null ? null : java.util.Arrays.asList(m_categories)); + sb.append(", category: ").append(m_category); + sb.append(", content: ").append(m_content); + sb.append(", create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", end-time: ").append(m_endTime); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", metric: ").append(m_metric); + sb.append(", start-time: ").append(m_startTime); + sb.append(", type: ").append(m_type); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/ServerAlarmRule.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/ServerAlarmRule.java new file mode 100644 index 0000000000..ee25153dc0 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/ServerAlarmRule.java @@ -0,0 +1,179 @@ +package com.dianping.cat.alarm; + + +public class ServerAlarmRule { + private long m_id; + + private String m_category; + + private String m_endPoint; + + private String m_measurement; + + private String m_tags; + + private String m_content; + + private String m_type; + + private String m_creator; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public String getCategory() { + return m_category; + } + + public String getContent() { + return m_content; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getCreator() { + return m_creator; + } + + public String getEndPoint() { + return m_endPoint; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public String getMeasurement() { + return m_measurement; + } + + public String getTags() { + return m_tags; + } + + public String getType() { + return m_type; + } + + public java.util.Date getUpdatetime() { + return m_updateTime; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public ServerAlarmRule setCategory(String category) { + m_category = category; + return this; + } + + public ServerAlarmRule setContent(String content) { + m_content = content; + return this; + } + + public ServerAlarmRule setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public ServerAlarmRule setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public ServerAlarmRule setCreator(String creator) { + m_creator = creator; + return this; + } + + public ServerAlarmRule setEndPoint(String endPoint) { + m_endPoint = endPoint; + return this; + } + + public ServerAlarmRule setId(int id) { + m_id = id; + m_keyId = id; + return this; + } + + public ServerAlarmRule setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public ServerAlarmRule setKeyId(int keyId) { + m_keyId = keyId; + return this; + } + + public ServerAlarmRule setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public ServerAlarmRule setMeasurement(String measurement) { + m_measurement = measurement; + return this; + } + + public ServerAlarmRule setTags(String tags) { + m_tags = tags; + return this; + } + + public ServerAlarmRule setType(String type) { + m_type = type; + return this; + } + + public ServerAlarmRule setUpdatetime(java.util.Date updatetime) { + m_updateTime = updatetime; + return this; + } + + public ServerAlarmRule setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("ServerAlarmRule["); + sb.append("category: ").append(m_category); + sb.append(", content: ").append(m_content); + sb.append(", create-time: ").append(m_createTime); + sb.append(", creator: ").append(m_creator); + sb.append(", end-point: ").append(m_endPoint); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", measurement: ").append(m_measurement); + sb.append(", tags: ").append(m_tags); + sb.append(", type: ").append(m_type); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/UserDefineRule.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/UserDefineRule.java new file mode 100644 index 0000000000..70ed7ded6a --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/UserDefineRule.java @@ -0,0 +1,115 @@ +package com.dianping.cat.alarm; + + +public class UserDefineRule { + private long m_id; + + private String m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + + private long m_maxId; + public void afterLoad() { + m_keyId = m_id; + } + + public String getContent() { + return m_content; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public long getMaxId() { + return m_maxId; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public UserDefineRule setContent(String content) { + m_content = content; + return this; + } + + public UserDefineRule setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public UserDefineRule setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public UserDefineRule setId(int id) { + m_id = id; + m_keyId = id; + return this; + } + + public UserDefineRule setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public UserDefineRule setKeyId(int keyId) { + m_keyId = keyId; + return this; + } + + public UserDefineRule setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public UserDefineRule setMaxId(int maxId) { + m_maxId = maxId; + return this; + } + + public UserDefineRule setMaxId(long maxId) { + m_maxId = maxId; + return this; + } + + public UserDefineRule setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("UserDefineRule["); + sb.append("content: ").append(m_content); + sb.append(", create-time: ").append(m_createTime); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", max-id: ").append(m_maxId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/BaseEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/BaseEntity.java new file mode 100644 index 0000000000..fcd9cd02b3 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.alarm.policy; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.alarm.policy.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/Constants.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/Constants.java new file mode 100644 index 0000000000..2de9d8fb83 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/Constants.java @@ -0,0 +1,26 @@ +package com.dianping.cat.alarm.policy; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ATTR_RECOVERMINUTE = "recoverMinute"; + + public static final String ATTR_SEND = "send"; + + public static final String ATTR_SUSPENDMINUTE = "suspendMinute"; + + public static final String ENTITY_ALERT_POLICY = "alert-policy"; + + public static final String ENTITY_GROUP = "group"; + + public static final String ENTITY_GROUPS = "groups"; + + public static final String ENTITY_LEVEL = "level"; + + public static final String ENTITY_LEVELS = "levels"; + + public static final String ENTITY_TYPE = "type"; + + public static final String ENTITY_TYPES = "types"; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IEntity.java new file mode 100644 index 0000000000..1bddc46d2c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.alarm.policy; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IVisitor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IVisitor.java new file mode 100644 index 0000000000..3c09a897d0 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/IVisitor.java @@ -0,0 +1,17 @@ +package com.dianping.cat.alarm.policy; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public interface IVisitor { + + public void visitAlertPolicy(AlertPolicy alertPolicy); + + public void visitGroup(Group group); + + public void visitLevel(Level level); + + public void visitType(Type type); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/AlertPolicy.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/AlertPolicy.java new file mode 100644 index 0000000000..0812cf78c9 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/AlertPolicy.java @@ -0,0 +1,83 @@ +package com.dianping.cat.alarm.policy.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.policy.BaseEntity; +import com.dianping.cat.alarm.policy.IVisitor; + +public class AlertPolicy extends BaseEntity { + private Map m_types = new LinkedHashMap(); + + public AlertPolicy() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAlertPolicy(this); + } + + public AlertPolicy addType(Type type) { + m_types.put(type.getId(), type); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AlertPolicy) { + AlertPolicy _o = (AlertPolicy) obj; + + if (!equals(getTypes(), _o.getTypes())) { + return false; + } + + + return true; + } + + return false; + } + + public Type findType(String id) { + return m_types.get(id); + } + + public Type findOrCreateType(String id) { + Type type = m_types.get(id); + + if (type == null) { + synchronized (m_types) { + type = m_types.get(id); + + if (type == null) { + type = new Type(id); + m_types.put(id, type); + } + } + } + + return type; + } + + public Map getTypes() { + return m_types; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_types == null ? 0 : m_types.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(AlertPolicy other) { + } + + public Type removeType(String id) { + return m_types.remove(id); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Group.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Group.java new file mode 100644 index 0000000000..cae86c01d6 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Group.java @@ -0,0 +1,102 @@ +package com.dianping.cat.alarm.policy.entity; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_GROUP; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.policy.BaseEntity; +import com.dianping.cat.alarm.policy.IVisitor; + +public class Group extends BaseEntity { + private String m_id; + + private Map m_levels = new LinkedHashMap(); + + public Group() { + } + + public Group(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGroup(this); + } + + public Group addLevel(Level level) { + m_levels.put(level.getId(), level); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Group) { + Group _o = (Group) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Level findLevel(String id) { + return m_levels.get(id); + } + + public Level findOrCreateLevel(String id) { + Level level = m_levels.get(id); + + if (level == null) { + synchronized (m_levels) { + level = m_levels.get(id); + + if (level == null) { + level = new Level(id); + m_levels.put(id, level); + } + } + } + + return level; + } + + public String getId() { + return m_id; + } + + public Map getLevels() { + return m_levels; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Group other) { + assertAttributeEquals(other, ENTITY_GROUP, ATTR_ID, m_id, other.getId()); + + } + + public Level removeLevel(String id) { + return m_levels.remove(id); + } + + public Group setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Level.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Level.java new file mode 100644 index 0000000000..2aac2c6b7f --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Level.java @@ -0,0 +1,107 @@ +package com.dianping.cat.alarm.policy.entity; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_LEVEL; + +import com.dianping.cat.alarm.policy.BaseEntity; +import com.dianping.cat.alarm.policy.IVisitor; + +public class Level extends BaseEntity { + private String m_id; + + private String m_send; + + private Integer m_suspendMinute; + + private Integer m_recoverMinute; + + public Level() { + } + + public Level(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitLevel(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Level) { + Level _o = (Level) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public Integer getRecoverMinute() { + return m_recoverMinute; + } + + public String getSend() { + return m_send; + } + + public Integer getSuspendMinute() { + return m_suspendMinute; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Level other) { + assertAttributeEquals(other, ENTITY_LEVEL, ATTR_ID, m_id, other.getId()); + + if (other.getSend() != null) { + m_send = other.getSend(); + } + + if (other.getSuspendMinute() != null) { + m_suspendMinute = other.getSuspendMinute(); + } + + if (other.getRecoverMinute() != null) { + m_recoverMinute = other.getRecoverMinute(); + } + } + + public Level setId(String id) { + m_id = id; + return this; + } + + public Level setRecoverMinute(Integer recoverMinute) { + m_recoverMinute = recoverMinute; + return this; + } + + public Level setSend(String send) { + m_send = send; + return this; + } + + public Level setSuspendMinute(Integer suspendMinute) { + m_suspendMinute = suspendMinute; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Type.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Type.java new file mode 100644 index 0000000000..3eeab28f53 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/entity/Type.java @@ -0,0 +1,102 @@ +package com.dianping.cat.alarm.policy.entity; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_TYPE; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.policy.BaseEntity; +import com.dianping.cat.alarm.policy.IVisitor; + +public class Type extends BaseEntity { + private String m_id; + + private Map m_groups = new LinkedHashMap(); + + public Type() { + } + + public Type(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitType(this); + } + + public Type addGroup(Group group) { + m_groups.put(group.getId(), group); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Type) { + Type _o = (Type) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Group findGroup(String id) { + return m_groups.get(id); + } + + public Group findOrCreateGroup(String id) { + Group group = m_groups.get(id); + + if (group == null) { + synchronized (m_groups) { + group = m_groups.get(id); + + if (group == null) { + group = new Group(id); + m_groups.put(id, group); + } + } + } + + return group; + } + + public Map getGroups() { + return m_groups; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Type other) { + assertAttributeEquals(other, ENTITY_TYPE, ATTR_ID, m_id, other.getId()); + + } + + public Group removeGroup(String id) { + return m_groups.remove(id); + } + + public Type setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomMaker.java new file mode 100644 index 0000000000..d0fd90d155 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomMaker.java @@ -0,0 +1,116 @@ +package com.dianping.cat.alarm.policy.transform; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ATTR_RECOVERMINUTE; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SEND; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SUSPENDMINUTE; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultDomMaker implements IMaker { + + @Override + public AlertPolicy buildAlertPolicy(Node node) { + AlertPolicy alertPolicy = new AlertPolicy(); + + return alertPolicy; + } + + @Override + public Group buildGroup(Node node) { + String id = getAttribute(node, ATTR_ID); + + Group group = new Group(id); + + return group; + } + + @Override + public Level buildLevel(Node node) { + String id = getAttribute(node, ATTR_ID); + String send = getAttribute(node, ATTR_SEND); + String suspendMinute = getAttribute(node, ATTR_SUSPENDMINUTE); + String recoverMinute = getAttribute(node, ATTR_RECOVERMINUTE); + + Level level = new Level(id); + + if (send != null) { + level.setSend(send); + } + + if (suspendMinute != null) { + level.setSuspendMinute(convert(Integer.class, suspendMinute, null)); + } + + if (recoverMinute != null) { + level.setRecoverMinute(convert(Integer.class, recoverMinute, null)); + } + + return level; + } + + @Override + public Type buildType(Node node) { + String id = getAttribute(node, ATTR_ID); + + Type type = new Type(id); + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected String getAttribute(Node node, String name) { + Node attribute = node.getAttributes().getNamedItem(name); + + return attribute == null ? null : attribute.getNodeValue(); + } + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomParser.java new file mode 100644 index 0000000000..0a38445621 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultDomParser.java @@ -0,0 +1,149 @@ +package com.dianping.cat.alarm.policy.transform; + +import static com.dianping.cat.alarm.policy.Constants.ENTITY_ALERT_POLICY; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_GROUP; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_LEVEL; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_TYPE; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultDomParser implements IParser { + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } + + protected List getChildTagNodes(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (name == null || child.getNodeName().equals(name)) { + nodes.add(child); + } + } + } + + return nodes; + } + + protected Node getDocument(String xml) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + dbf.setIgnoringElementContentWhitespace(true); + dbf.setIgnoringComments(true); + + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + + return db.parse(new InputSource(new StringReader(xml))); + } catch (Exception x) { + throw new RuntimeException(x); + } + } + + protected List getGrandChildTagNodes(Node parent, String name) { + Node child = getChildTagNode(parent, name); + NodeList children = child == null ? null : child.getChildNodes(); + int len = children == null ? 0 : children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node grandChild = children.item(i); + + if (grandChild.getNodeType() == Node.ELEMENT_NODE) { + nodes.add(grandChild); + } + } + + return nodes; + } + + public AlertPolicy parse(Node node) { + return parse(new DefaultDomMaker(), new DefaultLinker(false), node); + } + + public AlertPolicy parse(String xml) throws SAXException, IOException { + Node doc = getDocument(xml); + Node rootNode = getChildTagNode(doc, ENTITY_ALERT_POLICY); + + if (rootNode == null) { + throw new RuntimeException(String.format("alert-policy element(%s) is expected!", ENTITY_ALERT_POLICY)); + } + + return parse(new DefaultDomMaker(), new DefaultLinker(false), rootNode); + } + + public AlertPolicy parse(IMaker maker, ILinker linker, Node node) { + AlertPolicy alertPolicy = maker.buildAlertPolicy(node); + + if (node != null) { + AlertPolicy parent = alertPolicy; + + for (Node child : getChildTagNodes(node, ENTITY_TYPE)) { + Type type = maker.buildType(child); + + if (linker.onType(parent, type)) { + parseForType(maker, linker, type, child); + } + } + } + + return alertPolicy; + } + + public void parseForGroup(IMaker maker, ILinker linker, Group parent, Node node) { + for (Node child : getChildTagNodes(node, ENTITY_LEVEL)) { + Level level = maker.buildLevel(child); + + if (linker.onLevel(parent, level)) { + parseForLevel(maker, linker, level, child); + } + } + } + + public void parseForLevel(IMaker maker, ILinker linker, Level parent, Node node) { + } + + public void parseForType(IMaker maker, ILinker linker, Type parent, Node node) { + for (Node child : getChildTagNodes(node, ENTITY_GROUP)) { + Group group = maker.buildGroup(child); + + if (linker.onGroup(parent, group)) { + parseForGroup(maker, linker, group, child); + } + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultLinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultLinker.java new file mode 100644 index 0000000000..2c2031ca07 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultLinker.java @@ -0,0 +1,72 @@ +package com.dianping.cat.alarm.policy.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onGroup(final Type parent, final Group group) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addGroup(group); + } + }); + } else { + parent.addGroup(group); + } + + return true; + } + + @Override + public boolean onLevel(final Group parent, final Level level) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addLevel(level); + } + }); + } else { + parent.addLevel(level); + } + + return true; + } + + @Override + public boolean onType(final AlertPolicy parent, final Type type) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addType(type); + } + }); + } else { + parent.addType(type); + } + + return true; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..5404bc19c7 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxMaker.java @@ -0,0 +1,89 @@ +package com.dianping.cat.alarm.policy.transform; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ATTR_RECOVERMINUTE; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SEND; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SUSPENDMINUTE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AlertPolicy buildAlertPolicy(Attributes attributes) { + AlertPolicy alertPolicy = new AlertPolicy(); + + return alertPolicy; + } + + @Override + public Group buildGroup(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Group group = new Group(id); + + return group; + } + + @Override + public Level buildLevel(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String send = attributes.getValue(ATTR_SEND); + String suspendMinute = attributes.getValue(ATTR_SUSPENDMINUTE); + String recoverMinute = attributes.getValue(ATTR_RECOVERMINUTE); + Level level = new Level(id); + + if (send != null) { + level.setSend(send); + } + + if (suspendMinute != null) { + level.setSuspendMinute(convert(Integer.class, suspendMinute, null)); + } + + if (recoverMinute != null) { + level.setRecoverMinute(convert(Integer.class, recoverMinute, null)); + } + + return level; + } + + @Override + public Type buildType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Type type = new Type(id); + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..3eba9a572b --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultSaxParser.java @@ -0,0 +1,273 @@ +package com.dianping.cat.alarm.policy.transform; + +import static com.dianping.cat.alarm.policy.Constants.ENTITY_ALERT_POLICY; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_GROUP; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_LEVEL; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.alarm.policy.IEntity; +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static AlertPolicy parse(InputStream in) throws SAXException, IOException { + return parseEntity(AlertPolicy.class, new InputSource(removeBOM(in))); + } + + public static AlertPolicy parse(Reader reader) throws SAXException, IOException { + return parseEntity(AlertPolicy.class, new InputSource(removeBOM(reader))); + } + + public static AlertPolicy parse(String xml) throws SAXException, IOException { + return parseEntity(AlertPolicy.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAlertPolicy(AlertPolicy parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_linker.onType(parentObj, type); + m_objs.push(type); + } else { + throw new SAXException(String.format("Element(%s) is not expected under alert-policy!", qName)); + } + + m_tags.push(qName); + } + + private void parseForGroup(Group parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_LEVEL.equals(qName)) { + Level level = m_maker.buildLevel(attributes); + + m_linker.onLevel(parentObj, level); + m_objs.push(level); + } else { + throw new SAXException(String.format("Element(%s) is not expected under group!", qName)); + } + + m_tags.push(qName); + } + + private void parseForLevel(Level parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForType(Type parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_GROUP.equals(qName)) { + Group group = m_maker.buildGroup(attributes); + + m_linker.onGroup(parentObj, group); + m_objs.push(group); + } else { + throw new SAXException(String.format("Element(%s) is not expected under type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_ALERT_POLICY.equals(qName)) { + AlertPolicy alertPolicy = m_maker.buildAlertPolicy(attributes); + + m_entity = alertPolicy; + m_objs.push(alertPolicy); + m_tags.push(qName); + } else if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_entity = type; + m_objs.push(type); + m_tags.push(qName); + } else if (ENTITY_GROUP.equals(qName)) { + Group group = m_maker.buildGroup(attributes); + + m_entity = group; + m_objs.push(group); + m_tags.push(qName); + } else if (ENTITY_LEVEL.equals(qName)) { + Level level = m_maker.buildLevel(attributes); + + m_entity = level; + m_objs.push(level); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof AlertPolicy) { + parseForAlertPolicy((AlertPolicy) parent, tag, qName, attributes); + } else if (parent instanceof Type) { + parseForType((Type) parent, tag, qName, attributes); + } else if (parent instanceof Group) { + parseForGroup((Group) parent, tag, qName, attributes); + } else if (parent instanceof Level) { + parseForLevel((Level) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultXmlBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..f8b3bf22eb --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/DefaultXmlBuilder.java @@ -0,0 +1,245 @@ +package com.dianping.cat.alarm.policy.transform; + +import static com.dianping.cat.alarm.policy.Constants.ATTR_ID; +import static com.dianping.cat.alarm.policy.Constants.ATTR_RECOVERMINUTE; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SEND; +import static com.dianping.cat.alarm.policy.Constants.ATTR_SUSPENDMINUTE; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_ALERT_POLICY; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_GROUP; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_LEVEL; +import static com.dianping.cat.alarm.policy.Constants.ENTITY_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.alarm.policy.IEntity; +import com.dianping.cat.alarm.policy.IVisitor; +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitAlertPolicy(AlertPolicy alertPolicy) { + startTag(ENTITY_ALERT_POLICY, null); + + if (!alertPolicy.getTypes().isEmpty()) { + for (Type type : alertPolicy.getTypes().values()) { + type.accept(m_visitor); + } + } + + endTag(ENTITY_ALERT_POLICY); + } + + @Override + public void visitGroup(Group group) { + startTag(ENTITY_GROUP, null, ATTR_ID, group.getId()); + + if (!group.getLevels().isEmpty()) { + for (Level level : group.getLevels().values()) { + level.accept(m_visitor); + } + } + + endTag(ENTITY_GROUP); + } + + @Override + public void visitLevel(Level level) { + startTag(ENTITY_LEVEL, true, null, ATTR_ID, level.getId(), ATTR_SEND, level.getSend(), ATTR_SUSPENDMINUTE, level.getSuspendMinute(), ATTR_RECOVERMINUTE, level.getRecoverMinute()); + } + + @Override + public void visitType(Type type) { + startTag(ENTITY_TYPE, null, ATTR_ID, type.getId()); + + if (!type.getGroups().isEmpty()) { + for (Group group : type.getGroups().values()) { + group.accept(m_visitor); + } + } + + endTag(ENTITY_TYPE); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/ILinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/ILinker.java new file mode 100644 index 0000000000..4d74e92727 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/ILinker.java @@ -0,0 +1,15 @@ +package com.dianping.cat.alarm.policy.transform; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public interface ILinker { + + public boolean onGroup(Type parent, Group group); + + public boolean onLevel(Group parent, Level level); + + public boolean onType(AlertPolicy parent, Type type); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IMaker.java new file mode 100644 index 0000000000..efce96ec78 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IMaker.java @@ -0,0 +1,17 @@ +package com.dianping.cat.alarm.policy.transform; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public interface IMaker { + + public AlertPolicy buildAlertPolicy(T node); + + public Group buildGroup(T node); + + public Level buildLevel(T node); + + public Type buildType(T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IParser.java new file mode 100644 index 0000000000..e9638dbf61 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/policy/transform/IParser.java @@ -0,0 +1,16 @@ +package com.dianping.cat.alarm.policy.transform; + +import com.dianping.cat.alarm.policy.entity.AlertPolicy; +import com.dianping.cat.alarm.policy.entity.Group; +import com.dianping.cat.alarm.policy.entity.Level; +import com.dianping.cat.alarm.policy.entity.Type; + +public interface IParser { + public AlertPolicy parse(IMaker maker, ILinker linker, T node); + + public void parseForGroup(IMaker maker, ILinker linker, Group parent, T node); + + public void parseForLevel(IMaker maker, ILinker linker, Level parent, T node); + + public void parseForType(IMaker maker, ILinker linker, Type parent, T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/BaseEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/BaseEntity.java new file mode 100644 index 0000000000..77a874569a --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.alarm.receiver; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.alarm.receiver.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/Constants.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/Constants.java new file mode 100644 index 0000000000..421ceec0e4 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/Constants.java @@ -0,0 +1,30 @@ +package com.dianping.cat.alarm.receiver; + +public class Constants { + + public static final String ATTR_ENABLE = "enable"; + + public static final String ATTR_ID = "id"; + + public static final String ELEMENT_DX = "dx"; + + public static final String ELEMENT_DXS = "dxs"; + + public static final String ELEMENT_EMAIL = "email"; + + public static final String ELEMENT_EMAILS = "emails"; + + public static final String ELEMENT_PHONE = "phone"; + + public static final String ELEMENT_PHONES = "phones"; + + public static final String ELEMENT_WEIXIN = "weixin"; + + public static final String ELEMENT_WEIXINS = "weixins"; + + public static final String ENTITY_ALERT_CONFIG = "alert-config"; + + public static final String ENTITY_RECEIVER = "receiver"; + + public static final String ENTITY_RECEIVERS = "receivers"; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IEntity.java new file mode 100644 index 0000000000..a5ee7e616e --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.alarm.receiver; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IVisitor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IVisitor.java new file mode 100644 index 0000000000..0bfc6780b1 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/IVisitor.java @@ -0,0 +1,11 @@ +package com.dianping.cat.alarm.receiver; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public interface IVisitor { + + public void visitAlertConfig(AlertConfig alertConfig); + + public void visitReceiver(Receiver receiver); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/AlertConfig.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/AlertConfig.java new file mode 100644 index 0000000000..46998d24ac --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/AlertConfig.java @@ -0,0 +1,106 @@ +package com.dianping.cat.alarm.receiver.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.receiver.BaseEntity; +import com.dianping.cat.alarm.receiver.IVisitor; + +public class AlertConfig extends BaseEntity { + private Map m_receivers = new LinkedHashMap(); + + private Boolean m_enable; + + public AlertConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAlertConfig(this); + } + + public AlertConfig addReceiver(Receiver receiver) { + m_receivers.put(receiver.getId(), receiver); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AlertConfig) { + AlertConfig _o = (AlertConfig) obj; + + if (!equals(getReceivers(), _o.getReceivers())) { + return false; + } + + if (!equals(getEnable(), _o.getEnable())) { + return false; + } + + + return true; + } + + return false; + } + + public Receiver findReceiver(String id) { + return m_receivers.get(id); + } + + public Receiver findOrCreateReceiver(String id) { + Receiver receiver = m_receivers.get(id); + + if (receiver == null) { + synchronized (m_receivers) { + receiver = m_receivers.get(id); + + if (receiver == null) { + receiver = new Receiver(id); + m_receivers.put(id, receiver); + } + } + } + + return receiver; + } + + public Boolean getEnable() { + return m_enable; + } + + public Map getReceivers() { + return m_receivers; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_receivers == null ? 0 : m_receivers.hashCode()); + hash = hash * 31 + (m_enable == null ? 0 : m_enable.hashCode()); + + return hash; + } + + public boolean isEnable() { + return m_enable != null && m_enable.booleanValue(); + } + + @Override + public void mergeAttributes(AlertConfig other) { + if (other.getEnable() != null) { + m_enable = other.getEnable(); + } + } + + public Receiver removeReceiver(String id) { + return m_receivers.remove(id); + } + + public AlertConfig setEnable(Boolean enable) { + m_enable = enable; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/Receiver.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/Receiver.java new file mode 100644 index 0000000000..ebdcaacb12 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/entity/Receiver.java @@ -0,0 +1,128 @@ +package com.dianping.cat.alarm.receiver.entity; + +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ID; +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_RECEIVER; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.receiver.BaseEntity; +import com.dianping.cat.alarm.receiver.IVisitor; + +public class Receiver extends BaseEntity { + private String m_id; + + private Boolean m_enable; + + private List m_emails = new ArrayList(); + + private List m_dxs = new ArrayList(); + + private List m_phones = new ArrayList(); + + private List m_weixins = new ArrayList(); + + public Receiver() { + } + + public Receiver(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitReceiver(this); + } + + public Receiver addDx(String dx) { + m_dxs.add(dx); + return this; + } + + public Receiver addEmail(String email) { + m_emails.add(email); + return this; + } + + public Receiver addPhone(String phone) { + m_phones.add(phone); + return this; + } + + public Receiver addWeixin(String weixin) { + m_weixins.add(weixin); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Receiver) { + Receiver _o = (Receiver) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public List getDxs() { + return m_dxs; + } + + public List getEmails() { + return m_emails; + } + + public Boolean getEnable() { + return m_enable; + } + + public String getId() { + return m_id; + } + + public List getPhones() { + return m_phones; + } + + public List getWeixins() { + return m_weixins; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public boolean isEnable() { + return m_enable != null && m_enable.booleanValue(); + } + + @Override + public void mergeAttributes(Receiver other) { + assertAttributeEquals(other, ENTITY_RECEIVER, ATTR_ID, m_id, other.getId()); + + if (other.getEnable() != null) { + m_enable = other.getEnable(); + } + } + + public Receiver setEnable(Boolean enable) { + m_enable = enable; + return this; + } + + public Receiver setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomMaker.java new file mode 100644 index 0000000000..e9569c5908 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomMaker.java @@ -0,0 +1,132 @@ +package com.dianping.cat.alarm.receiver.transform; + +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ENABLE; +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ID; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultDomMaker implements IMaker { + + @Override + public AlertConfig buildAlertConfig(Node node) { + String enable = getAttribute(node, ATTR_ENABLE); + + AlertConfig alertConfig = new AlertConfig(); + + if (enable != null) { + alertConfig.setEnable(convert(Boolean.class, enable, null)); + } + + return alertConfig; + } + + @Override + public String buildDx(Node node) { + return getText(node); + } + + @Override + public String buildEmail(Node node) { + return getText(node); + } + + @Override + public String buildPhone(Node node) { + return getText(node); + } + + @Override + public Receiver buildReceiver(Node node) { + String id = getAttribute(node, ATTR_ID); + String enable = getAttribute(node, ATTR_ENABLE); + + Receiver receiver = new Receiver(id); + + if (enable != null) { + receiver.setEnable(convert(Boolean.class, enable, null)); + } + + return receiver; + } + + @Override + public String buildWeixin(Node node) { + return getText(node); + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected String getAttribute(Node node, String name) { + Node attribute = node.getAttributes().getNamedItem(name); + + return attribute == null ? null : attribute.getNodeValue(); + } + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } + + protected String getText(Node node) { + if (node != null) { + StringBuilder sb = new StringBuilder(); + NodeList children = node.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.TEXT_NODE || child.getNodeType() == Node.CDATA_SECTION_NODE) { + sb.append(child.getNodeValue()); + } + } + + if (sb.length() != 0) { + return sb.toString(); + } + } + + return null; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomParser.java new file mode 100644 index 0000000000..49cea115c5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultDomParser.java @@ -0,0 +1,153 @@ +package com.dianping.cat.alarm.receiver.transform; + +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_DX; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_EMAIL; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_PHONE; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_WEIXIN; + +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_ALERT_CONFIG; +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_RECEIVER; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultDomParser implements IParser { + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } + + protected List getChildTagNodes(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (name == null || child.getNodeName().equals(name)) { + nodes.add(child); + } + } + } + + return nodes; + } + + protected Node getDocument(String xml) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + dbf.setIgnoringElementContentWhitespace(true); + dbf.setIgnoringComments(true); + + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + + return db.parse(new InputSource(new StringReader(xml))); + } catch (Exception x) { + throw new RuntimeException(x); + } + } + + protected List getGrandChildTagNodes(Node parent, String name) { + Node child = getChildTagNode(parent, name); + NodeList children = child == null ? null : child.getChildNodes(); + int len = children == null ? 0 : children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node grandChild = children.item(i); + + if (grandChild.getNodeType() == Node.ELEMENT_NODE) { + nodes.add(grandChild); + } + } + + return nodes; + } + + public AlertConfig parse(Node node) { + return parse(new DefaultDomMaker(), new DefaultLinker(false), node); + } + + public AlertConfig parse(String xml) throws SAXException, IOException { + Node doc = getDocument(xml); + Node rootNode = getChildTagNode(doc, ENTITY_ALERT_CONFIG); + + if (rootNode == null) { + throw new RuntimeException(String.format("alert-config element(%s) is expected!", ENTITY_ALERT_CONFIG)); + } + + return parse(new DefaultDomMaker(), new DefaultLinker(false), rootNode); + } + + public AlertConfig parse(IMaker maker, ILinker linker, Node node) { + AlertConfig alertConfig = maker.buildAlertConfig(node); + + if (node != null) { + AlertConfig parent = alertConfig; + + for (Node child : getChildTagNodes(node, ENTITY_RECEIVER)) { + Receiver receiver = maker.buildReceiver(child); + + if (linker.onReceiver(parent, receiver)) { + parseForReceiver(maker, linker, receiver, child); + } + } + } + + return alertConfig; + } + + public void parseForReceiver(IMaker maker, ILinker linker, Receiver parent, Node node) { + for (Node child : getChildTagNodes(node, ELEMENT_EMAIL)) { + String email = maker.buildEmail(child); + + parent.addEmail(email); + } + + for (Node child : getChildTagNodes(node, ELEMENT_DX)) { + String dx = maker.buildDx(child); + + parent.addDx(dx); + } + + for (Node child : getChildTagNodes(node, ELEMENT_PHONE)) { + String phone = maker.buildPhone(child); + + parent.addPhone(phone); + } + + for (Node child : getChildTagNodes(node, ELEMENT_WEIXIN)) { + String weixin = maker.buildWeixin(child); + + parent.addWeixin(weixin); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultLinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultLinker.java new file mode 100644 index 0000000000..9377631af9 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultLinker.java @@ -0,0 +1,38 @@ +package com.dianping.cat.alarm.receiver.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onReceiver(final AlertConfig parent, final Receiver receiver) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addReceiver(receiver); + } + }); + } else { + parent.addReceiver(receiver); + } + + return true; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..ba3a3f1dc3 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxMaker.java @@ -0,0 +1,84 @@ +package com.dianping.cat.alarm.receiver.transform; + +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ENABLE; +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ID; + +import org.xml.sax.Attributes; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AlertConfig buildAlertConfig(Attributes attributes) { + String enable = attributes.getValue(ATTR_ENABLE); + AlertConfig alertConfig = new AlertConfig(); + + if (enable != null) { + alertConfig.setEnable(convert(Boolean.class, enable, null)); + } + + return alertConfig; + } + + @Override + public String buildDx(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public String buildEmail(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public String buildPhone(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Receiver buildReceiver(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String enable = attributes.getValue(ATTR_ENABLE); + Receiver receiver = new Receiver(id); + + if (enable != null) { + receiver.setEnable(convert(Boolean.class, enable, null)); + } + + return receiver; + } + + @Override + public String buildWeixin(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..e777e9d77a --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultSaxParser.java @@ -0,0 +1,254 @@ +package com.dianping.cat.alarm.receiver.transform; + +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_DX; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_DXS; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_EMAIL; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_EMAILS; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_PHONE; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_PHONES; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_WEIXIN; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_WEIXINS; + +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_ALERT_CONFIG; +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_RECEIVER; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.alarm.receiver.IEntity; +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static AlertConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(AlertConfig.class, new InputSource(removeBOM(in))); + } + + public static AlertConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(AlertConfig.class, new InputSource(removeBOM(reader))); + } + + public static AlertConfig parse(String xml) throws SAXException, IOException { + return parseEntity(AlertConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof Receiver) { + Receiver receiver = (Receiver) currentObj; + + if (ELEMENT_EMAIL.equals(currentTag)) { + receiver.addEmail(getText()); + } else if (ELEMENT_DX.equals(currentTag)) { + receiver.addDx(getText()); + } else if (ELEMENT_PHONE.equals(currentTag)) { + receiver.addPhone(getText()); + } else if (ELEMENT_WEIXIN.equals(currentTag)) { + receiver.addWeixin(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAlertConfig(AlertConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_RECEIVER.equals(qName)) { + Receiver receiver = m_maker.buildReceiver(attributes); + + m_linker.onReceiver(parentObj, receiver); + m_objs.push(receiver); + } else { + throw new SAXException(String.format("Element(%s) is not expected under alert-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForReceiver(Receiver parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_EMAILS.equals(qName) || ELEMENT_EMAIL.equals(qName) || ELEMENT_DXS.equals(qName) || ELEMENT_DX.equals(qName) || ELEMENT_PHONES.equals(qName) || ELEMENT_PHONE.equals(qName) || ELEMENT_WEIXINS.equals(qName) || ELEMENT_WEIXIN.equals(qName)) { + m_objs.push(parentObj); + } else { + throw new SAXException(String.format("Element(%s) is not expected under receiver!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_ALERT_CONFIG.equals(qName)) { + AlertConfig alertConfig = m_maker.buildAlertConfig(attributes); + + m_entity = alertConfig; + m_objs.push(alertConfig); + m_tags.push(qName); + } else if (ENTITY_RECEIVER.equals(qName)) { + Receiver receiver = m_maker.buildReceiver(attributes); + + m_entity = receiver; + m_objs.push(receiver); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof AlertConfig) { + parseForAlertConfig((AlertConfig) parent, tag, qName, attributes); + } else if (parent instanceof Receiver) { + parseForReceiver((Receiver) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultXmlBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..ce4867f688 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/DefaultXmlBuilder.java @@ -0,0 +1,286 @@ +package com.dianping.cat.alarm.receiver.transform; + +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ENABLE; +import static com.dianping.cat.alarm.receiver.Constants.ATTR_ID; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_DX; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_EMAIL; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_PHONE; +import static com.dianping.cat.alarm.receiver.Constants.ELEMENT_WEIXIN; +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_ALERT_CONFIG; +import static com.dianping.cat.alarm.receiver.Constants.ENTITY_RECEIVER; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.alarm.receiver.IEntity; +import com.dianping.cat.alarm.receiver.IVisitor; +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + @Override + public void visitAlertConfig(AlertConfig alertConfig) { + startTag(ENTITY_ALERT_CONFIG, null, ATTR_ENABLE, alertConfig.getEnable()); + + if (!alertConfig.getReceivers().isEmpty()) { + for (Receiver receiver : alertConfig.getReceivers().values()) { + receiver.accept(m_visitor); + } + } + + endTag(ENTITY_ALERT_CONFIG); + } + + @Override + public void visitReceiver(Receiver receiver) { + startTag(ENTITY_RECEIVER, null, ATTR_ID, receiver.getId(), ATTR_ENABLE, receiver.getEnable()); + + if (!receiver.getEmails().isEmpty()) { + for (String email : receiver.getEmails()) { + tagWithText(ELEMENT_EMAIL, email); + } + } + + if (!receiver.getDxs().isEmpty()) { + for (String dx : receiver.getDxs()) { + tagWithText(ELEMENT_DX, dx); + } + } + + if (!receiver.getPhones().isEmpty()) { + for (String phone : receiver.getPhones()) { + tagWithText(ELEMENT_PHONE, phone); + } + } + + if (!receiver.getWeixins().isEmpty()) { + for (String weixin : receiver.getWeixins()) { + tagWithText(ELEMENT_WEIXIN, weixin); + } + } + + endTag(ENTITY_RECEIVER); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/ILinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/ILinker.java new file mode 100644 index 0000000000..c56cd0a11a --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/ILinker.java @@ -0,0 +1,9 @@ +package com.dianping.cat.alarm.receiver.transform; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public interface ILinker { + + public boolean onReceiver(AlertConfig parent, Receiver receiver); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IMaker.java new file mode 100644 index 0000000000..f1612ff1c5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IMaker.java @@ -0,0 +1,19 @@ +package com.dianping.cat.alarm.receiver.transform; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public interface IMaker { + + public AlertConfig buildAlertConfig(T node); + + public String buildDx(T node); + + public String buildEmail(T node); + + public String buildPhone(T node); + + public Receiver buildReceiver(T node); + + public String buildWeixin(T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IParser.java new file mode 100644 index 0000000000..4c90c5a657 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/receiver/transform/IParser.java @@ -0,0 +1,10 @@ +package com.dianping.cat.alarm.receiver.transform; + +import com.dianping.cat.alarm.receiver.entity.AlertConfig; +import com.dianping.cat.alarm.receiver.entity.Receiver; + +public interface IParser { + public AlertConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForReceiver(IMaker maker, ILinker linker, Receiver parent, T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/BaseEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/BaseEntity.java new file mode 100644 index 0000000000..c04c49f8e9 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/BaseEntity.java @@ -0,0 +1,56 @@ +package com.dianping.cat.alarm.rule; + +import java.util.Formattable; +import java.util.FormattableFlags; +import java.util.Formatter; + +import com.dianping.cat.alarm.rule.transform.DefaultXmlBuilder; +import com.dianping.cat.alarm.rule.transform.DefaultJsonBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String JSON = "%#.3s"; + + public static final String JSON_COMPACT = "%#s"; + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean useJson = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE; + boolean compact = (precision <= 0); + + if (useJson) { + DefaultJsonBuilder builder = new DefaultJsonBuilder(compact); + + formatter.format("%s", builder.build(this)); + } else { + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/Constants.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/Constants.java new file mode 100644 index 0000000000..ed44b37c0c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/Constants.java @@ -0,0 +1,54 @@ +package com.dianping.cat.alarm.rule; + +public class Constants { + + public static final String ATTR_ALERTTYPE = "alertType"; + + public static final String ATTR_AVAILABLE = "available"; + + public static final String ATTR_ENDTIME = "endtime"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_METRICITEMTEXT = "metricItemText"; + + public static final String ATTR_MINUTE = "minute"; + + public static final String ATTR_MONITORAVG = "monitorAvg"; + + public static final String ATTR_MONITORCOUNT = "monitorCount"; + + public static final String ATTR_MONITORSUM = "monitorSum"; + + public static final String ATTR_PRODUCTTEXT = "productText"; + + public static final String ATTR_STARTTIME = "starttime"; + + public static final String ATTR_TEXT = "text"; + + public static final String ATTR_TITLE = "title"; + + public static final String ATTR_TYPE = "type"; + + public static final String ENTITY_CONDITION = "condition"; + + public static final String ENTITY_CONDITIONS = "conditions"; + + public static final String ENTITY_CONFIG = "config"; + + public static final String ENTITY_CONFIGS = "configs"; + + public static final String ENTITY_METRIC_ITEM = "metric-item"; + + public static final String ENTITY_METRIC_ITEMS = "metric-items"; + + public static final String ENTITY_MONITOR_RULES = "monitor-rules"; + + public static final String ENTITY_RULE = "rule"; + + public static final String ENTITY_RULES = "rules"; + + public static final String ENTITY_SUB_CONDITION = "sub-condition"; + + public static final String ENTITY_SUB_CONDITIONS = "sub-conditions"; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IEntity.java new file mode 100644 index 0000000000..6b34588ba5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.alarm.rule; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IVisitor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IVisitor.java new file mode 100644 index 0000000000..1ac211f563 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/IVisitor.java @@ -0,0 +1,23 @@ +package com.dianping.cat.alarm.rule; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public interface IVisitor { + + public void visitCondition(Condition condition); + + public void visitConfig(Config config); + + public void visitMetricItem(MetricItem metricItem); + + public void visitMonitorRules(MonitorRules monitorRules); + + public void visitRule(Rule rule); + + public void visitSubCondition(SubCondition subCondition); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Condition.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Condition.java new file mode 100644 index 0000000000..8db90c3b32 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Condition.java @@ -0,0 +1,120 @@ +package com.dianping.cat.alarm.rule.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class Condition extends BaseEntity { + private Integer m_minute = 3; + + private List m_subConditions = new ArrayList(); + + private String m_title; + + private String m_alertType = "error"; + + public Condition() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCondition(this); + } + + public Condition addSubCondition(SubCondition subCondition) { + m_subConditions.add(subCondition); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Condition) { + Condition _o = (Condition) obj; + + if (!equals(getMinute(), _o.getMinute())) { + return false; + } + + if (!equals(getSubConditions(), _o.getSubConditions())) { + return false; + } + + if (!equals(getTitle(), _o.getTitle())) { + return false; + } + + if (!equals(getAlertType(), _o.getAlertType())) { + return false; + } + + + return true; + } + + return false; + } + + public String getAlertType() { + return m_alertType; + } + + public Integer getMinute() { + return m_minute; + } + + public List getSubConditions() { + return m_subConditions; + } + + public String getTitle() { + return m_title; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_minute == null ? 0 : m_minute.hashCode()); + for (SubCondition e : m_subConditions) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + hash = hash * 31 + (m_title == null ? 0 : m_title.hashCode()); + hash = hash * 31 + (m_alertType == null ? 0 : m_alertType.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Condition other) { + if (other.getMinute() != null) { + m_minute = other.getMinute(); + } + + if (other.getTitle() != null) { + m_title = other.getTitle(); + } + + if (other.getAlertType() != null) { + m_alertType = other.getAlertType(); + } + } + + public Condition setAlertType(String alertType) { + m_alertType = alertType; + return this; + } + + public Condition setMinute(Integer minute) { + m_minute = minute; + return this; + } + + public Condition setTitle(String title) { + m_title = title; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Config.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Config.java new file mode 100644 index 0000000000..6da3f1d71e --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Config.java @@ -0,0 +1,100 @@ +package com.dianping.cat.alarm.rule.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class Config extends BaseEntity { + private String m_starttime; + + private String m_endtime; + + private List m_conditions = new ArrayList(); + + public Config() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitConfig(this); + } + + public Config addCondition(Condition condition) { + m_conditions.add(condition); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Config) { + Config _o = (Config) obj; + + if (!equals(getStarttime(), _o.getStarttime())) { + return false; + } + + if (!equals(getEndtime(), _o.getEndtime())) { + return false; + } + + if (!equals(getConditions(), _o.getConditions())) { + return false; + } + + + return true; + } + + return false; + } + + public List getConditions() { + return m_conditions; + } + + public String getEndtime() { + return m_endtime; + } + + public String getStarttime() { + return m_starttime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_starttime == null ? 0 : m_starttime.hashCode()); + hash = hash * 31 + (m_endtime == null ? 0 : m_endtime.hashCode()); + for (Condition e : m_conditions) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + + return hash; + } + + @Override + public void mergeAttributes(Config other) { + if (other.getStarttime() != null) { + m_starttime = other.getStarttime(); + } + + if (other.getEndtime() != null) { + m_endtime = other.getEndtime(); + } + } + + public Config setEndtime(String endtime) { + m_endtime = endtime; + return this; + } + + public Config setStarttime(String starttime) { + m_starttime = starttime; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MetricItem.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MetricItem.java new file mode 100644 index 0000000000..51ab107c01 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MetricItem.java @@ -0,0 +1,150 @@ +package com.dianping.cat.alarm.rule.entity; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class MetricItem extends BaseEntity { + private Boolean m_monitorCount; + + private Boolean m_monitorSum; + + private Boolean m_monitorAvg; + + private String m_metricItemText; + + private String m_productText; + + public MetricItem() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMetricItem(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MetricItem) { + MetricItem _o = (MetricItem) obj; + + if (!equals(getMonitorCount(), _o.getMonitorCount())) { + return false; + } + + if (!equals(getMonitorSum(), _o.getMonitorSum())) { + return false; + } + + if (!equals(getMonitorAvg(), _o.getMonitorAvg())) { + return false; + } + + if (!equals(getMetricItemText(), _o.getMetricItemText())) { + return false; + } + + if (!equals(getProductText(), _o.getProductText())) { + return false; + } + + + return true; + } + + return false; + } + + public String getMetricItemText() { + return m_metricItemText; + } + + public Boolean getMonitorAvg() { + return m_monitorAvg; + } + + public Boolean getMonitorCount() { + return m_monitorCount; + } + + public Boolean getMonitorSum() { + return m_monitorSum; + } + + public String getProductText() { + return m_productText; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_monitorCount == null ? 0 : m_monitorCount.hashCode()); + hash = hash * 31 + (m_monitorSum == null ? 0 : m_monitorSum.hashCode()); + hash = hash * 31 + (m_monitorAvg == null ? 0 : m_monitorAvg.hashCode()); + hash = hash * 31 + (m_metricItemText == null ? 0 : m_metricItemText.hashCode()); + hash = hash * 31 + (m_productText == null ? 0 : m_productText.hashCode()); + + return hash; + } + + public boolean isMonitorAvg() { + return m_monitorAvg != null && m_monitorAvg.booleanValue(); + } + + public boolean isMonitorCount() { + return m_monitorCount != null && m_monitorCount.booleanValue(); + } + + public boolean isMonitorSum() { + return m_monitorSum != null && m_monitorSum.booleanValue(); + } + + @Override + public void mergeAttributes(MetricItem other) { + if (other.getMonitorCount() != null) { + m_monitorCount = other.getMonitorCount(); + } + + if (other.getMonitorSum() != null) { + m_monitorSum = other.getMonitorSum(); + } + + if (other.getMonitorAvg() != null) { + m_monitorAvg = other.getMonitorAvg(); + } + + if (other.getMetricItemText() != null) { + m_metricItemText = other.getMetricItemText(); + } + + if (other.getProductText() != null) { + m_productText = other.getProductText(); + } + } + + public MetricItem setMetricItemText(String metricItemText) { + m_metricItemText = metricItemText; + return this; + } + + public MetricItem setMonitorAvg(Boolean monitorAvg) { + m_monitorAvg = monitorAvg; + return this; + } + + public MetricItem setMonitorCount(Boolean monitorCount) { + m_monitorCount = monitorCount; + return this; + } + + public MetricItem setMonitorSum(Boolean monitorSum) { + m_monitorSum = monitorSum; + return this; + } + + public MetricItem setProductText(String productText) { + m_productText = productText; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MonitorRules.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MonitorRules.java new file mode 100644 index 0000000000..5c859b23c0 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/MonitorRules.java @@ -0,0 +1,83 @@ +package com.dianping.cat.alarm.rule.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class MonitorRules extends BaseEntity { + private Map m_rules = new LinkedHashMap(); + + public MonitorRules() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMonitorRules(this); + } + + public MonitorRules addRule(Rule rule) { + m_rules.put(rule.getId(), rule); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MonitorRules) { + MonitorRules _o = (MonitorRules) obj; + + if (!equals(getRules(), _o.getRules())) { + return false; + } + + + return true; + } + + return false; + } + + public Rule findRule(String id) { + return m_rules.get(id); + } + + public Rule findOrCreateRule(String id) { + Rule rule = m_rules.get(id); + + if (rule == null) { + synchronized (m_rules) { + rule = m_rules.get(id); + + if (rule == null) { + rule = new Rule(id); + m_rules.put(id, rule); + } + } + } + + return rule; + } + + public Map getRules() { + return m_rules; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_rules == null ? 0 : m_rules.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(MonitorRules other) { + } + + public Rule removeRule(String id) { + return m_rules.remove(id); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Rule.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Rule.java new file mode 100644 index 0000000000..d75351279b --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/Rule.java @@ -0,0 +1,126 @@ +package com.dianping.cat.alarm.rule.entity; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULE; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class Rule extends BaseEntity { + private String m_id; + + private Boolean m_available; + + private List m_metricItems = new ArrayList(); + + private List m_configs = new ArrayList(); + + private Map m_dynamicAttributes = new LinkedHashMap(); + + public Rule() { + } + + public Rule(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRule(this); + } + + public Rule addConfig(Config config) { + m_configs.add(config); + return this; + } + + public Rule addMetricItem(MetricItem metricItem) { + m_metricItems.add(metricItem); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Rule) { + Rule _o = (Rule) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getDynamicAttribute(String name) { + return m_dynamicAttributes.get(name); + } + + public Map getDynamicAttributes() { + return m_dynamicAttributes; + } + + public Boolean getAvailable() { + return m_available; + } + + public List getConfigs() { + return m_configs; + } + + public String getId() { + return m_id; + } + + public List getMetricItems() { + return m_metricItems; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public boolean isAvailable() { + return m_available != null && m_available.booleanValue(); + } + + @Override + public void mergeAttributes(Rule other) { + assertAttributeEquals(other, ENTITY_RULE, ATTR_ID, m_id, other.getId()); + + for (Map.Entry e : other.getDynamicAttributes().entrySet()) { + m_dynamicAttributes.put(e.getKey(), e.getValue()); + } + + if (other.getAvailable() != null) { + m_available = other.getAvailable(); + } + } + + public void setDynamicAttribute(String name, String value) { + m_dynamicAttributes.put(name, value); + } + + public Rule setAvailable(Boolean available) { + m_available = available; + return this; + } + + public Rule setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/SubCondition.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/SubCondition.java new file mode 100644 index 0000000000..04de3a6b70 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/entity/SubCondition.java @@ -0,0 +1,78 @@ +package com.dianping.cat.alarm.rule.entity; + +import com.dianping.cat.alarm.rule.BaseEntity; +import com.dianping.cat.alarm.rule.IVisitor; + +public class SubCondition extends BaseEntity { + private String m_type; + + private String m_text; + + public SubCondition() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSubCondition(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SubCondition) { + SubCondition _o = (SubCondition) obj; + + if (!equals(getType(), _o.getType())) { + return false; + } + + if (!equals(getText(), _o.getText())) { + return false; + } + + + return true; + } + + return false; + } + + public String getText() { + return m_text; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_type == null ? 0 : m_type.hashCode()); + hash = hash * 31 + (m_text == null ? 0 : m_text.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(SubCondition other) { + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getText() != null) { + m_text = other.getText(); + } + } + + public SubCondition setText(String text) { + m_text = text; + return this; + } + + public SubCondition setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomMaker.java new file mode 100644 index 0000000000..7013972986 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomMaker.java @@ -0,0 +1,208 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ALERTTYPE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_AVAILABLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ENDTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ATTR_METRICITEMTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MINUTE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORAVG; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORCOUNT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORSUM; +import static com.dianping.cat.alarm.rule.Constants.ATTR_PRODUCTTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_STARTTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TITLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TYPE; + +import java.util.Map; + +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultDomMaker implements IMaker { + + @Override + public Condition buildCondition(Node node) { + String minute = getAttribute(node, ATTR_MINUTE); + String title = getAttribute(node, ATTR_TITLE); + String alertType = getAttribute(node, ATTR_ALERTTYPE); + + Condition condition = new Condition(); + + if (minute != null) { + condition.setMinute(convert(Integer.class, minute, null)); + } + + if (title != null) { + condition.setTitle(title); + } + + if (alertType != null) { + condition.setAlertType(alertType); + } + + return condition; + } + + @Override + public Config buildConfig(Node node) { + String starttime = getAttribute(node, ATTR_STARTTIME); + String endtime = getAttribute(node, ATTR_ENDTIME); + + Config config = new Config(); + + if (starttime != null) { + config.setStarttime(starttime); + } + + if (endtime != null) { + config.setEndtime(endtime); + } + + return config; + } + + @Override + public MetricItem buildMetricItem(Node node) { + String monitorCount = getAttribute(node, ATTR_MONITORCOUNT); + String monitorSum = getAttribute(node, ATTR_MONITORSUM); + String monitorAvg = getAttribute(node, ATTR_MONITORAVG); + String metricItemText = getAttribute(node, ATTR_METRICITEMTEXT); + String productText = getAttribute(node, ATTR_PRODUCTTEXT); + + MetricItem metricItem = new MetricItem(); + + if (monitorCount != null) { + metricItem.setMonitorCount(convert(Boolean.class, monitorCount, null)); + } + + if (monitorSum != null) { + metricItem.setMonitorSum(convert(Boolean.class, monitorSum, null)); + } + + if (monitorAvg != null) { + metricItem.setMonitorAvg(convert(Boolean.class, monitorAvg, null)); + } + + if (metricItemText != null) { + metricItem.setMetricItemText(metricItemText); + } + + if (productText != null) { + metricItem.setProductText(productText); + } + + return metricItem; + } + + @Override + public MonitorRules buildMonitorRules(Node node) { + MonitorRules monitorRules = new MonitorRules(); + + return monitorRules; + } + + @Override + public Rule buildRule(Node node) { + String id = getAttribute(node, ATTR_ID); + String available = getAttribute(node, ATTR_AVAILABLE); + + Rule rule = new Rule(id); + + if (available != null) { + rule.setAvailable(convert(Boolean.class, available, null)); + } + + Map dynamicAttributes = rule.getDynamicAttributes(); + NamedNodeMap attributes = node.getAttributes(); + int length = attributes == null ? 0 : attributes.getLength(); + + for (int i = 0; i < length; i++) { + Node item = attributes.item(i); + + dynamicAttributes.put(item.getNodeName(), item.getNodeValue()); + } + + dynamicAttributes.remove(ATTR_ID); + dynamicAttributes.remove(ATTR_AVAILABLE); + + return rule; + } + + @Override + public SubCondition buildSubCondition(Node node) { + String type = getAttribute(node, ATTR_TYPE); + String text = getAttribute(node, ATTR_TEXT); + + SubCondition subCondition = new SubCondition(); + + if (type != null) { + subCondition.setType(type); + } + + if (text != null) { + subCondition.setText(text); + } + + return subCondition; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected String getAttribute(Node node, String name) { + Node attribute = node.getAttributes().getNamedItem(name); + + return attribute == null ? null : attribute.getNodeValue(); + } + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomParser.java new file mode 100644 index 0000000000..5f094d55bb --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultDomParser.java @@ -0,0 +1,174 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONDITION; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONFIG; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_METRIC_ITEM; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_MONITOR_RULES; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_SUB_CONDITION; + +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultDomParser implements IParser { + + protected Node getChildTagNode(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals(name)) { + return child; + } + } + } + + return null; + } + + protected List getChildTagNodes(Node parent, String name) { + NodeList children = parent.getChildNodes(); + int len = children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node child = children.item(i); + + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (name == null || child.getNodeName().equals(name)) { + nodes.add(child); + } + } + } + + return nodes; + } + + protected Node getDocument(String xml) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + dbf.setIgnoringElementContentWhitespace(true); + dbf.setIgnoringComments(true); + + try { + DocumentBuilder db = dbf.newDocumentBuilder(); + + return db.parse(new InputSource(new StringReader(xml))); + } catch (Exception x) { + throw new RuntimeException(x); + } + } + + protected List getGrandChildTagNodes(Node parent, String name) { + Node child = getChildTagNode(parent, name); + NodeList children = child == null ? null : child.getChildNodes(); + int len = children == null ? 0 : children.getLength(); + List nodes = new ArrayList(len); + + for (int i = 0; i < len; i++) { + Node grandChild = children.item(i); + + if (grandChild.getNodeType() == Node.ELEMENT_NODE) { + nodes.add(grandChild); + } + } + + return nodes; + } + + public MonitorRules parse(Node node) { + return parse(new DefaultDomMaker(), new DefaultLinker(false), node); + } + + public MonitorRules parse(String xml) throws SAXException, IOException { + Node doc = getDocument(xml); + Node rootNode = getChildTagNode(doc, ENTITY_MONITOR_RULES); + + if (rootNode == null) { + throw new RuntimeException(String.format("monitor-rules element(%s) is expected!", ENTITY_MONITOR_RULES)); + } + + return parse(new DefaultDomMaker(), new DefaultLinker(false), rootNode); + } + + public MonitorRules parse(IMaker maker, ILinker linker, Node node) { + MonitorRules monitorRules = maker.buildMonitorRules(node); + + if (node != null) { + MonitorRules parent = monitorRules; + + for (Node child : getChildTagNodes(node, ENTITY_RULE)) { + Rule rule = maker.buildRule(child); + + if (linker.onRule(parent, rule)) { + parseForRule(maker, linker, rule, child); + } + } + } + + return monitorRules; + } + + public void parseForCondition(IMaker maker, ILinker linker, Condition parent, Node node) { + for (Node child : getChildTagNodes(node, ENTITY_SUB_CONDITION)) { + SubCondition subCondition = maker.buildSubCondition(child); + + if (linker.onSubCondition(parent, subCondition)) { + parseForSubCondition(maker, linker, subCondition, child); + } + } + } + + public void parseForConfig(IMaker maker, ILinker linker, Config parent, Node node) { + for (Node child : getChildTagNodes(node, ENTITY_CONDITION)) { + Condition condition = maker.buildCondition(child); + + if (linker.onCondition(parent, condition)) { + parseForCondition(maker, linker, condition, child); + } + } + } + + public void parseForMetricItem(IMaker maker, ILinker linker, MetricItem parent, Node node) { + } + + public void parseForRule(IMaker maker, ILinker linker, Rule parent, Node node) { + for (Node child : getChildTagNodes(node, ENTITY_METRIC_ITEM)) { + MetricItem metricItem = maker.buildMetricItem(child); + + if (linker.onMetricItem(parent, metricItem)) { + parseForMetricItem(maker, linker, metricItem, child); + } + } + + for (Node child : getChildTagNodes(node, ENTITY_CONFIG)) { + Config config = maker.buildConfig(child); + + if (linker.onConfig(parent, config)) { + parseForConfig(maker, linker, config, child); + } + } + } + + public void parseForSubCondition(IMaker maker, ILinker linker, SubCondition parent, Node node) { + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonBuilder.java new file mode 100644 index 0000000000..ab63a98090 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonBuilder.java @@ -0,0 +1,345 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ALERTTYPE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_AVAILABLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ENDTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ATTR_METRICITEMTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MINUTE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORAVG; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORCOUNT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORSUM; +import static com.dianping.cat.alarm.rule.Constants.ATTR_PRODUCTTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_STARTTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TITLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONDITIONS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONFIGS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_METRIC_ITEMS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULES; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_SUB_CONDITIONS; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + +import com.dianping.cat.alarm.rule.IEntity; +import com.dianping.cat.alarm.rule.IVisitor; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultJsonBuilder implements IVisitor { + + private IVisitor m_visitor; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultJsonBuilder() { + this(false); + } + + public DefaultJsonBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultJsonBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_visitor = this; + } + + protected void arrayBegin(String name) { + indent(); + m_sb.append('"').append(name).append(m_compact ? "\":[" : "\": [\r\n"); + m_level++; + } + + protected void arrayEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append("],").append(m_compact ? "" : "\r\n"); + } + + protected void attributes(Map dynamicAttributes, Object... nameValues) { + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + if (attrValue instanceof Collection) { + @SuppressWarnings("unchecked") + Collection items = (Collection) attrValue; + + if (!items.isEmpty()) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (Object item : items) { + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else if (attrValue.getClass().isArray()) { + int length = Array.getLength(attrValue); + + if (length > 0) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (int j = 0; j < length; j++) { + Object item = Array.get(attrValue, j); + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else { + if (m_compact) { + m_sb.append('"').append(attrName).append("\":"); + toString(m_sb, attrValue); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(attrName).append("\": "); + toString(m_sb, attrValue); + m_sb.append(",\r\n"); + } + } + } + } + + if (dynamicAttributes != null) { + for (Map.Entry e : dynamicAttributes.entrySet()) { + if (m_compact) { + m_sb.append('"').append(e.getKey()).append("\":"); + toString(m_sb, e.getValue()); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(e.getKey()).append("\": "); + toString(m_sb, e.getValue()); + m_sb.append(",\r\n"); + } + } + } + } + + public String build(IEntity entity) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + trimComma(); + + return m_sb.toString(); + } + + public String buildArray(Collection> entities) { + m_sb.append('['); + + if (entities != null) { + for (IEntity entity : entities) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + } + + trimComma(); + } + + m_sb.append(']'); + + return m_sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void objectBegin(String name) { + indent(); + + if (name == null) { + m_sb.append("{").append(m_compact ? "" : "\r\n"); + } else { + m_sb.append('"').append(name).append(m_compact ? "\":{" : "\": {\r\n"); + } + + m_level++; + } + + protected void objectEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append(m_compact ? "}," : "},\r\n"); + } + + protected void toString(StringBuilder sb, Object value) { + if (value == null) { + sb.append("null"); + } else if (value instanceof Boolean || value instanceof Number) { + sb.append(value); + } else { + String val = value.toString(); + int len = val.length(); + + sb.append('"'); + + for (int i = 0; i < len; i++) { + char ch = val.charAt(i); + + switch (ch) { + case '\\': + case '/': + case '"': + sb.append('\\').append(ch); + break; + case '\t': + sb.append("\\t"); + break; + case '\r': + sb.append("\\r"); + break; + case '\n': + sb.append("\\n"); + break; + default: + sb.append(ch); + break; + } + } + + sb.append('"'); + } + } + + protected void trimComma() { + int len = m_sb.length(); + + if (m_compact) { + if (len > 1 && m_sb.charAt(len - 1) == ',') { + m_sb.replace(len - 1, len, ""); + } + } else { + if (len > 3 && m_sb.charAt(len - 3) == ',') { + m_sb.replace(len - 3, len - 2, ""); + } + } + } + + @Override + public void visitCondition(Condition condition) { + attributes(null, ATTR_MINUTE, condition.getMinute(), ATTR_TITLE, condition.getTitle(), ATTR_ALERTTYPE, condition.getAlertType()); + + if (!condition.getSubConditions().isEmpty()) { + arrayBegin(ENTITY_SUB_CONDITIONS); + + for (SubCondition subCondition : condition.getSubConditions()) { + objectBegin(null); + subCondition.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_SUB_CONDITIONS); + } + } + + @Override + public void visitConfig(Config config) { + attributes(null, ATTR_STARTTIME, config.getStarttime(), ATTR_ENDTIME, config.getEndtime()); + + if (!config.getConditions().isEmpty()) { + arrayBegin(ENTITY_CONDITIONS); + + for (Condition condition : config.getConditions()) { + objectBegin(null); + condition.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_CONDITIONS); + } + } + + @Override + public void visitMetricItem(MetricItem metricItem) { + attributes(null, ATTR_MONITORCOUNT, metricItem.getMonitorCount(), ATTR_MONITORSUM, metricItem.getMonitorSum(), ATTR_MONITORAVG, metricItem.getMonitorAvg(), ATTR_METRICITEMTEXT, metricItem.getMetricItemText(), ATTR_PRODUCTTEXT, metricItem.getProductText()); + } + + @Override + public void visitMonitorRules(MonitorRules monitorRules) { + + if (!monitorRules.getRules().isEmpty()) { + objectBegin(ENTITY_RULES); + + for (Map.Entry e : monitorRules.getRules().entrySet()) { + String key = String.valueOf(e.getKey()); + + objectBegin(key); + e.getValue().accept(m_visitor); + objectEnd(key); + } + + objectEnd(ENTITY_RULES); + } + } + + @Override + public void visitRule(Rule rule) { + attributes(rule.getDynamicAttributes(), ATTR_ID, rule.getId(), ATTR_AVAILABLE, rule.getAvailable()); + + if (!rule.getMetricItems().isEmpty()) { + arrayBegin(ENTITY_METRIC_ITEMS); + + for (MetricItem metricItem : rule.getMetricItems()) { + objectBegin(null); + metricItem.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_METRIC_ITEMS); + } + + if (!rule.getConfigs().isEmpty()) { + arrayBegin(ENTITY_CONFIGS); + + for (Config config : rule.getConfigs()) { + objectBegin(null); + config.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_CONFIGS); + } + } + + @Override + public void visitSubCondition(SubCondition subCondition) { + attributes(null, ATTR_TYPE, subCondition.getType(), ATTR_TEXT, subCondition.getText()); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonParser.java new file mode 100644 index 0000000000..aacf426030 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultJsonParser.java @@ -0,0 +1,489 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ALERTTYPE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_AVAILABLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ENDTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ATTR_METRICITEMTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MINUTE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORAVG; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORCOUNT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORSUM; +import static com.dianping.cat.alarm.rule.Constants.ATTR_PRODUCTTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_STARTTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TITLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONDITIONS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONFIGS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_METRIC_ITEMS; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULES; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_SUB_CONDITIONS; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.dianping.cat.alarm.rule.IEntity; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultJsonParser { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private List m_entities = new ArrayList(); + + private Class m_entityClass; + + private DefaultJsonParser(Class entityClass) { + m_entityClass = entityClass; + } + + public static > T parse(Class entityClass, InputStream in) throws IOException { + return parse(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > T parse(Class entityClass, Reader reader) throws IOException { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.onArrayBegin(); + parser.parse(new JsonReader(reader)); + parser.onArrayEnd(); + + if (parser.m_entities.isEmpty()) { + return null; + } else { + return (T) parser.m_entities.get(0); + } + } + + public static > T parse(Class entityClass, String json) throws IOException { + return parse(entityClass, new StringReader(json)); + } + + public static > List parseArray(Class entityClass, InputStream in) throws Exception { + return parseArray(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > List parseArray(Class entityClass, Reader reader) throws Exception { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.parse(new JsonReader(reader)); + return (List) (List) parser.m_entities; + } + + public static > List parseArray(Class entityClass, String json) throws Exception { + return parseArray(entityClass, new StringReader(json)); + } + + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + private Object createRootEntity() { + try { + Object entity = m_entityClass.newInstance(); + + return entity; + } catch (Exception e) { + throw new RuntimeException(String.format("Unable to create entity(%s) instance!", m_entityClass.getName()), e); + } + } + + private boolean isTopLevel() { + return m_objs.size() == 1; + } + + protected void onArrayBegin() { + if (m_objs.isEmpty()) { + m_objs.push(m_entities); + m_tags.push(""); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof Rule) { + if (ENTITY_METRIC_ITEMS.equals(tag)) { + m_objs.push(parent); + } else if (ENTITY_CONFIGS.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else if (parent instanceof Config) { + if (ENTITY_CONDITIONS.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else if (parent instanceof Condition) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } } + + protected void onArrayEnd() { + m_objs.pop(); + m_tags.pop(); + + } + protected void onName(String name) { + m_tags.push(name); + } + + protected void onObjectBegin() { + if (isTopLevel()) { + m_objs.push(createRootEntity()); + m_tags.push(""); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof MonitorRules) { + if (ENTITY_RULES.equals(tag)) { + m_objs.push(parent); + } else { + String parentTag = m_tags.size() >= 2 ? m_tags.get(m_tags.size() - 2) : null; + + if (ENTITY_RULES.equals(parentTag)) { + Rule rules = new Rule(); + + m_linker.onRule((MonitorRules) parent, rules); + m_objs.push(rules); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } + } else if (parent instanceof Rule) { + if (ENTITY_METRIC_ITEMS.equals(tag)) { + MetricItem metricItems = new MetricItem(); + + m_linker.onMetricItem((Rule) parent, metricItems); + m_objs.push(metricItems); + m_tags.push(""); + } else if (ENTITY_CONFIGS.equals(tag)) { + Config configs = new Config(); + + m_linker.onConfig((Rule) parent, configs); + m_objs.push(configs); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else if (parent instanceof Config) { + if (ENTITY_CONDITIONS.equals(tag)) { + Condition conditions = new Condition(); + + m_linker.onCondition((Config) parent, conditions); + m_objs.push(conditions); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else if (parent instanceof Condition) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + SubCondition subConditions = new SubCondition(); + + m_linker.onSubCondition((Condition) parent, subConditions); + m_objs.push(subConditions); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } + } + + protected void onObjectEnd() { + m_tags.pop(); + + Object entity = m_objs.pop(); + + if (isTopLevel()) { + m_entities.add(entity); + } + } + + protected void onValue(String value) { + Object parent = m_objs.peek(); + String tag = m_tags.pop(); + + if (parent instanceof MonitorRules) { + parseForMonitorRules((MonitorRules) parent, tag, value); + } else if (parent instanceof Rule) { + parseForRule((Rule) parent, tag, value); + } else if (parent instanceof MetricItem) { + parseForMetricItem((MetricItem) parent, tag, value); + } else if (parent instanceof Config) { + parseForConfig((Config) parent, tag, value); + } else if (parent instanceof Condition) { + parseForCondition((Condition) parent, tag, value); + } else if (parent instanceof SubCondition) { + parseForSubCondition((SubCondition) parent, tag, value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) under %s!", tag, parent)); + } + } + + private void parse(JsonReader reader) throws IOException { + try { + reader.parse(this); + } catch (EOFException e) { + if (m_objs.size() > 1) { + throw new EOFException(String.format("Unexpected end while parsing json! tags: %s.", m_tags)); + } + } + + m_linker.finish(); + } + + public void parseForCondition(Condition condition, String tag, String value) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + // do nothing here + } else if (ATTR_MINUTE.equals(tag)) { + condition.setMinute(convert(Integer.class, value, null)); + } else if (ATTR_TITLE.equals(tag)) { + condition.setTitle(value); + } else if (ATTR_ALERTTYPE.equals(tag)) { + condition.setAlertType(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, condition, m_tags)); + } + } + + public void parseForConfig(Config config, String tag, String value) { + if (ENTITY_CONDITIONS.equals(tag)) { + // do nothing here + } else if (ATTR_STARTTIME.equals(tag)) { + config.setStarttime(value); + } else if (ATTR_ENDTIME.equals(tag)) { + config.setEndtime(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, config, m_tags)); + } + } + + public void parseForMetricItem(MetricItem metricItem, String tag, String value) { + if (ATTR_MONITORCOUNT.equals(tag)) { + metricItem.setMonitorCount(convert(Boolean.class, value, null)); + } else if (ATTR_MONITORSUM.equals(tag)) { + metricItem.setMonitorSum(convert(Boolean.class, value, null)); + } else if (ATTR_MONITORAVG.equals(tag)) { + metricItem.setMonitorAvg(convert(Boolean.class, value, null)); + } else if (ATTR_METRICITEMTEXT.equals(tag)) { + metricItem.setMetricItemText(value); + } else if (ATTR_PRODUCTTEXT.equals(tag)) { + metricItem.setProductText(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, metricItem, m_tags)); + } + } + + public void parseForMonitorRules(MonitorRules monitorRules, String tag, String value) { + if (ENTITY_RULES.equals(tag)) { + // do nothing here + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, monitorRules, m_tags)); + } + } + + public void parseForRule(Rule rule, String tag, String value) { + if (ENTITY_METRIC_ITEMS.equals(tag) || ENTITY_CONFIGS.equals(tag)) { + // do nothing here + } else if (ATTR_ID.equals(tag)) { + rule.setId(value); + } else if (ATTR_AVAILABLE.equals(tag)) { + rule.setAvailable(convert(Boolean.class, value, null)); + } else { + rule.setDynamicAttribute(tag, value); + } + } + + public void parseForSubCondition(SubCondition subCondition, String tag, String value) { + if (ATTR_TYPE.equals(tag)) { + subCondition.setType(value); + } else if (ATTR_TEXT.equals(tag)) { + subCondition.setText(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, subCondition, m_tags)); + } + } + + + static class JsonReader { + private Reader m_reader; + + private char[] m_buffer = new char[2048]; + + private int m_size; + + private int m_index; + + public JsonReader(Reader reader) { + m_reader = reader; + } + + private char next() throws IOException { + if (m_index >= m_size) { + m_size = m_reader.read(m_buffer); + m_index = 0; + + if (m_size == -1) { + throw new EOFException(); + } + } + + return m_buffer[m_index++]; + } + + public void parse(DefaultJsonParser parser) throws IOException { + StringBuilder sb = new StringBuilder(); + boolean flag = false; + + while (true) { + char ch = next(); + + switch (ch) { + case ' ': + case '\t': + case '\r': + case '\n': + break; + case '{': + parser.onObjectBegin(); + flag = false; + break; + case '}': + if (flag) { // have value + parser.onValue(sb.toString()); + sb.setLength(0); + } + + parser.onObjectEnd(); + flag = false; + break; + case '\'': + case '"': + while (true) { + char ch2 = next(); + + if (ch2 != ch) { + if (ch2 == '\\') { + char ch3 = next(); + + switch (ch3) { + case 't': + sb.append('\t'); + break; + case 'r': + sb.append('\r'); + break; + case 'n': + sb.append('\n'); + break; + default: + sb.append(ch3); + break; + } + } else { + sb.append(ch2); + } + } else { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + flag = false; + } + + sb.setLength(0); + break; + } + } + + break; + case ':': + if (sb.length() != 0) { + parser.onName(sb.toString()); + sb.setLength(0); + } + + flag = true; + break; + case ',': + if (sb.length() != 0) { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + } + + sb.setLength(0); + } + + flag = false; + break; + case '[': + parser.onArrayBegin(); + flag = false; + break; + case ']': + parser.onArrayEnd(); + flag = false; + break; + default: + sb.append(ch); + break; + } + } + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultLinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultLinker.java new file mode 100644 index 0000000000..a6c53c4cc4 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultLinker.java @@ -0,0 +1,66 @@ +package com.dianping.cat.alarm.rule.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onCondition(final Config parent, final Condition condition) { + parent.addCondition(condition); + return true; + } + + @Override + public boolean onConfig(final Rule parent, final Config config) { + parent.addConfig(config); + return true; + } + + @Override + public boolean onMetricItem(final Rule parent, final MetricItem metricItem) { + parent.addMetricItem(metricItem); + return true; + } + + @Override + public boolean onRule(final MonitorRules parent, final Rule rule) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRule(rule); + } + }); + } else { + parent.addRule(rule); + } + + return true; + } + + @Override + public boolean onSubCondition(final Condition parent, final SubCondition subCondition) { + parent.addSubCondition(subCondition); + return true; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..5add42fdc5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxMaker.java @@ -0,0 +1,177 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ALERTTYPE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_AVAILABLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ENDTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ATTR_METRICITEMTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MINUTE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORAVG; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORCOUNT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORSUM; +import static com.dianping.cat.alarm.rule.Constants.ATTR_PRODUCTTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_STARTTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TITLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TYPE; + +import java.util.Map; +import org.xml.sax.Attributes; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Condition buildCondition(Attributes attributes) { + String minute = attributes.getValue(ATTR_MINUTE); + String title = attributes.getValue(ATTR_TITLE); + String alertType = attributes.getValue(ATTR_ALERTTYPE); + Condition condition = new Condition(); + + if (minute != null) { + condition.setMinute(convert(Integer.class, minute, null)); + } + + if (title != null) { + condition.setTitle(title); + } + + if (alertType != null) { + condition.setAlertType(alertType); + } + + return condition; + } + + @Override + public Config buildConfig(Attributes attributes) { + String starttime = attributes.getValue(ATTR_STARTTIME); + String endtime = attributes.getValue(ATTR_ENDTIME); + Config config = new Config(); + + if (starttime != null) { + config.setStarttime(starttime); + } + + if (endtime != null) { + config.setEndtime(endtime); + } + + return config; + } + + @Override + public MetricItem buildMetricItem(Attributes attributes) { + String monitorCount = attributes.getValue(ATTR_MONITORCOUNT); + String monitorSum = attributes.getValue(ATTR_MONITORSUM); + String monitorAvg = attributes.getValue(ATTR_MONITORAVG); + String metricItemText = attributes.getValue(ATTR_METRICITEMTEXT); + String productText = attributes.getValue(ATTR_PRODUCTTEXT); + MetricItem metricItem = new MetricItem(); + + if (monitorCount != null) { + metricItem.setMonitorCount(convert(Boolean.class, monitorCount, null)); + } + + if (monitorSum != null) { + metricItem.setMonitorSum(convert(Boolean.class, monitorSum, null)); + } + + if (monitorAvg != null) { + metricItem.setMonitorAvg(convert(Boolean.class, monitorAvg, null)); + } + + if (metricItemText != null) { + metricItem.setMetricItemText(metricItemText); + } + + if (productText != null) { + metricItem.setProductText(productText); + } + + return metricItem; + } + + @Override + public MonitorRules buildMonitorRules(Attributes attributes) { + MonitorRules monitorRules = new MonitorRules(); + + return monitorRules; + } + + @Override + public Rule buildRule(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String available = attributes.getValue(ATTR_AVAILABLE); + Rule rule = new Rule(id); + + if (available != null) { + rule.setAvailable(convert(Boolean.class, available, null)); + } + + Map dynamicAttributes = rule.getDynamicAttributes(); + int _length = attributes == null ? 0 : attributes.getLength(); + + for (int i = 0; i < _length; i++) { + String _name = attributes.getQName(i); + String _value = attributes.getValue(i); + + dynamicAttributes.put(_name, _value); + } + + dynamicAttributes.remove(ATTR_ID); + dynamicAttributes.remove(ATTR_AVAILABLE); + + return rule; + } + + @Override + public SubCondition buildSubCondition(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String text = attributes.getValue(ATTR_TEXT); + SubCondition subCondition = new SubCondition(); + + if (type != null) { + subCondition.setType(type); + } + + if (text != null) { + subCondition.setText(text); + } + + return subCondition; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..c77f620dc9 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultSaxParser.java @@ -0,0 +1,316 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONDITION; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONFIG; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_METRIC_ITEM; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_MONITOR_RULES; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_SUB_CONDITION; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.alarm.rule.IEntity; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static MonitorRules parse(InputStream in) throws SAXException, IOException { + return parseEntity(MonitorRules.class, new InputSource(removeBOM(in))); + } + + public static MonitorRules parse(Reader reader) throws SAXException, IOException { + return parseEntity(MonitorRules.class, new InputSource(removeBOM(reader))); + } + + public static MonitorRules parse(String xml) throws SAXException, IOException { + return parseEntity(MonitorRules.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForCondition(Condition parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SUB_CONDITION.equals(qName)) { + SubCondition subCondition = m_maker.buildSubCondition(attributes); + + m_linker.onSubCondition(parentObj, subCondition); + m_objs.push(subCondition); + } else { + throw new SAXException(String.format("Element(%s) is not expected under condition!", qName)); + } + + m_tags.push(qName); + } + + private void parseForConfig(Config parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_CONDITION.equals(qName)) { + Condition condition = m_maker.buildCondition(attributes); + + m_linker.onCondition(parentObj, condition); + m_objs.push(condition); + } else { + throw new SAXException(String.format("Element(%s) is not expected under config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForMetricItem(MetricItem parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMonitorRules(MonitorRules parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_RULE.equals(qName)) { + Rule rule = m_maker.buildRule(attributes); + + m_linker.onRule(parentObj, rule); + m_objs.push(rule); + } else { + throw new SAXException(String.format("Element(%s) is not expected under monitor-rules!", qName)); + } + + m_tags.push(qName); + } + + private void parseForRule(Rule parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_METRIC_ITEM.equals(qName)) { + MetricItem metricItem = m_maker.buildMetricItem(attributes); + + m_linker.onMetricItem(parentObj, metricItem); + m_objs.push(metricItem); + } else if (ENTITY_CONFIG.equals(qName)) { + Config config = m_maker.buildConfig(attributes); + + m_linker.onConfig(parentObj, config); + m_objs.push(config); + } else { + throw new SAXException(String.format("Element(%s) is not expected under rule!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSubCondition(SubCondition parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_MONITOR_RULES.equals(qName)) { + MonitorRules monitorRules = m_maker.buildMonitorRules(attributes); + + m_entity = monitorRules; + m_objs.push(monitorRules); + m_tags.push(qName); + } else if (ENTITY_RULE.equals(qName)) { + Rule rule = m_maker.buildRule(attributes); + + m_entity = rule; + m_objs.push(rule); + m_tags.push(qName); + } else if (ENTITY_METRIC_ITEM.equals(qName)) { + MetricItem metricItem = m_maker.buildMetricItem(attributes); + + m_entity = metricItem; + m_objs.push(metricItem); + m_tags.push(qName); + } else if (ENTITY_CONFIG.equals(qName)) { + Config config = m_maker.buildConfig(attributes); + + m_entity = config; + m_objs.push(config); + m_tags.push(qName); + } else if (ENTITY_CONDITION.equals(qName)) { + Condition condition = m_maker.buildCondition(attributes); + + m_entity = condition; + m_objs.push(condition); + m_tags.push(qName); + } else if (ENTITY_SUB_CONDITION.equals(qName)) { + SubCondition subCondition = m_maker.buildSubCondition(attributes); + + m_entity = subCondition; + m_objs.push(subCondition); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof MonitorRules) { + parseForMonitorRules((MonitorRules) parent, tag, qName, attributes); + } else if (parent instanceof Rule) { + parseForRule((Rule) parent, tag, qName, attributes); + } else if (parent instanceof MetricItem) { + parseForMetricItem((MetricItem) parent, tag, qName, attributes); + } else if (parent instanceof Config) { + parseForConfig((Config) parent, tag, qName, attributes); + } else if (parent instanceof Condition) { + parseForCondition((Condition) parent, tag, qName, attributes); + } else if (parent instanceof SubCondition) { + parseForSubCondition((SubCondition) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultXmlBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..f44de04786 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/DefaultXmlBuilder.java @@ -0,0 +1,283 @@ +package com.dianping.cat.alarm.rule.transform; + +import static com.dianping.cat.alarm.rule.Constants.ATTR_ALERTTYPE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_AVAILABLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ENDTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_ID; +import static com.dianping.cat.alarm.rule.Constants.ATTR_METRICITEMTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MINUTE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORAVG; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORCOUNT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_MONITORSUM; +import static com.dianping.cat.alarm.rule.Constants.ATTR_PRODUCTTEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_STARTTIME; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TEXT; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TITLE; +import static com.dianping.cat.alarm.rule.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONDITION; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_CONFIG; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_METRIC_ITEM; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_MONITOR_RULES; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_RULE; +import static com.dianping.cat.alarm.rule.Constants.ENTITY_SUB_CONDITION; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.alarm.rule.IEntity; +import com.dianping.cat.alarm.rule.IVisitor; +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitCondition(Condition condition) { + startTag(ENTITY_CONDITION, null, ATTR_MINUTE, condition.getMinute(), ATTR_TITLE, condition.getTitle(), ATTR_ALERTTYPE, condition.getAlertType()); + + if (!condition.getSubConditions().isEmpty()) { + for (SubCondition subCondition : condition.getSubConditions()) { + subCondition.accept(m_visitor); + } + } + + endTag(ENTITY_CONDITION); + } + + @Override + public void visitConfig(Config config) { + startTag(ENTITY_CONFIG, null, ATTR_STARTTIME, config.getStarttime(), ATTR_ENDTIME, config.getEndtime()); + + if (!config.getConditions().isEmpty()) { + for (Condition condition : config.getConditions()) { + condition.accept(m_visitor); + } + } + + endTag(ENTITY_CONFIG); + } + + @Override + public void visitMetricItem(MetricItem metricItem) { + startTag(ENTITY_METRIC_ITEM, true, null, ATTR_MONITORCOUNT, metricItem.getMonitorCount(), ATTR_MONITORSUM, metricItem.getMonitorSum(), ATTR_MONITORAVG, metricItem.getMonitorAvg(), ATTR_METRICITEMTEXT, metricItem.getMetricItemText(), ATTR_PRODUCTTEXT, metricItem.getProductText()); + } + + @Override + public void visitMonitorRules(MonitorRules monitorRules) { + startTag(ENTITY_MONITOR_RULES, null); + + if (!monitorRules.getRules().isEmpty()) { + for (Rule rule : monitorRules.getRules().values()) { + rule.accept(m_visitor); + } + } + + endTag(ENTITY_MONITOR_RULES); + } + + @Override + public void visitRule(Rule rule) { + startTag(ENTITY_RULE, rule.getDynamicAttributes(), ATTR_ID, rule.getId(), ATTR_AVAILABLE, rule.getAvailable()); + + if (!rule.getMetricItems().isEmpty()) { + for (MetricItem metricItem : rule.getMetricItems()) { + metricItem.accept(m_visitor); + } + } + + if (!rule.getConfigs().isEmpty()) { + for (Config config : rule.getConfigs()) { + config.accept(m_visitor); + } + } + + endTag(ENTITY_RULE); + } + + @Override + public void visitSubCondition(SubCondition subCondition) { + startTag(ENTITY_SUB_CONDITION, true, null, ATTR_TYPE, subCondition.getType(), ATTR_TEXT, subCondition.getText()); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/ILinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/ILinker.java new file mode 100644 index 0000000000..72003652dd --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/ILinker.java @@ -0,0 +1,21 @@ +package com.dianping.cat.alarm.rule.transform; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public interface ILinker { + + public boolean onCondition(Config parent, Condition condition); + + public boolean onConfig(Rule parent, Config config); + + public boolean onMetricItem(Rule parent, MetricItem metricItem); + + public boolean onRule(MonitorRules parent, Rule rule); + + public boolean onSubCondition(Condition parent, SubCondition subCondition); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IMaker.java new file mode 100644 index 0000000000..57739bb476 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IMaker.java @@ -0,0 +1,23 @@ +package com.dianping.cat.alarm.rule.transform; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public interface IMaker { + + public Condition buildCondition(T node); + + public Config buildConfig(T node); + + public MetricItem buildMetricItem(T node); + + public MonitorRules buildMonitorRules(T node); + + public Rule buildRule(T node); + + public SubCondition buildSubCondition(T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IParser.java new file mode 100644 index 0000000000..9bdc891979 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/rule/transform/IParser.java @@ -0,0 +1,22 @@ +package com.dianping.cat.alarm.rule.transform; + +import com.dianping.cat.alarm.rule.entity.Condition; +import com.dianping.cat.alarm.rule.entity.Config; +import com.dianping.cat.alarm.rule.entity.MetricItem; +import com.dianping.cat.alarm.rule.entity.MonitorRules; +import com.dianping.cat.alarm.rule.entity.Rule; +import com.dianping.cat.alarm.rule.entity.SubCondition; + +public interface IParser { + public MonitorRules parse(IMaker maker, ILinker linker, T node); + + public void parseForCondition(IMaker maker, ILinker linker, Condition parent, T node); + + public void parseForConfig(IMaker maker, ILinker linker, Config parent, T node); + + public void parseForMetricItem(IMaker maker, ILinker linker, MetricItem parent, T node); + + public void parseForRule(IMaker maker, ILinker linker, Rule parent, T node); + + public void parseForSubCondition(IMaker maker, ILinker linker, SubCondition parent, T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/BaseEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/BaseEntity.java new file mode 100644 index 0000000000..1d24677cd7 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.alarm.sender; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.alarm.sender.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/Constants.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/Constants.java new file mode 100644 index 0000000000..8f9c3a5dbc --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/Constants.java @@ -0,0 +1,24 @@ +package com.dianping.cat.alarm.sender; + +public class Constants { + + public static final String ATTR_BATCHSEND = "batchSend"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_SUCCESSCODE = "successCode"; + + public static final String ATTR_TYPE = "type"; + + public static final String ATTR_URL = "url"; + + public static final String ENTITY_PAR = "par"; + + public static final String ENTITY_PARS = "pars"; + + public static final String ENTITY_SENDER = "sender"; + + public static final String ENTITY_SENDERS = "senders"; + + public static final String ENTITY_SENDER_CONFIG = "sender-config"; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IEntity.java new file mode 100644 index 0000000000..6e4d39599e --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.alarm.sender; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IVisitor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IVisitor.java new file mode 100644 index 0000000000..5e8bde75a0 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.alarm.sender; + +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public interface IVisitor { + + public void visitPar(Par par); + + public void visitSender(Sender sender); + + public void visitSenderConfig(SenderConfig senderConfig); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Par.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Par.java new file mode 100644 index 0000000000..c3732b821c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Par.java @@ -0,0 +1,58 @@ +package com.dianping.cat.alarm.sender.entity; + +import com.dianping.cat.alarm.sender.BaseEntity; +import com.dianping.cat.alarm.sender.IVisitor; + +public class Par extends BaseEntity { + private String m_id; + + public Par() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitPar(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Par) { + Par _o = (Par) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Par other) { + if (other.getId() != null) { + m_id = other.getId(); + } + } + + public Par setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Sender.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Sender.java new file mode 100644 index 0000000000..4e2bb55af1 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/Sender.java @@ -0,0 +1,138 @@ +package com.dianping.cat.alarm.sender.entity; + +import static com.dianping.cat.alarm.sender.Constants.ATTR_ID; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_SENDER; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.sender.BaseEntity; +import com.dianping.cat.alarm.sender.IVisitor; + +public class Sender extends BaseEntity { + private String m_id; + + private String m_url; + + private String m_type; + + private String m_successCode; + + private boolean m_batchSend; + + private List m_pars = new ArrayList(); + + public Sender() { + } + + public Sender(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSender(this); + } + + public Sender addPar(Par par) { + m_pars.add(par); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Sender) { + Sender _o = (Sender) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public boolean getBatchSend() { + return m_batchSend; + } + + public String getId() { + return m_id; + } + + public List getPars() { + return m_pars; + } + + public String getSuccessCode() { + return m_successCode; + } + + public String getType() { + return m_type; + } + + public String getUrl() { + return m_url; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public boolean isBatchSend() { + return m_batchSend; + } + + @Override + public void mergeAttributes(Sender other) { + assertAttributeEquals(other, ENTITY_SENDER, ATTR_ID, m_id, other.getId()); + + if (other.getUrl() != null) { + m_url = other.getUrl(); + } + + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getSuccessCode() != null) { + m_successCode = other.getSuccessCode(); + } + + m_batchSend = other.getBatchSend(); + } + + public Sender setBatchSend(boolean batchSend) { + m_batchSend = batchSend; + return this; + } + + public Sender setId(String id) { + m_id = id; + return this; + } + + public Sender setSuccessCode(String successCode) { + m_successCode = successCode; + return this; + } + + public Sender setType(String type) { + m_type = type; + return this; + } + + public Sender setUrl(String url) { + m_url = url; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/SenderConfig.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/SenderConfig.java new file mode 100644 index 0000000000..c0e8aaf7be --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/entity/SenderConfig.java @@ -0,0 +1,66 @@ +package com.dianping.cat.alarm.sender.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.alarm.sender.BaseEntity; +import com.dianping.cat.alarm.sender.IVisitor; + +public class SenderConfig extends BaseEntity { + private Map m_senders = new LinkedHashMap(); + + public SenderConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSenderConfig(this); + } + + public SenderConfig addSender(Sender sender) { + m_senders.put(sender.getId(), sender); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SenderConfig) { + SenderConfig _o = (SenderConfig) obj; + + if (!equals(getSenders(), _o.getSenders())) { + return false; + } + + + return true; + } + + return false; + } + + public Sender findSender(String id) { + return m_senders.get(id); + } + + public Map getSenders() { + return m_senders; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_senders == null ? 0 : m_senders.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(SenderConfig other) { + } + + public Sender removeSender(String id) { + return m_senders.remove(id); + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultLinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultLinker.java new file mode 100644 index 0000000000..7f3326046c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultLinker.java @@ -0,0 +1,45 @@ +package com.dianping.cat.alarm.sender.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onPar(final Sender parent, final Par par) { + parent.addPar(par); + return true; + } + + @Override + public boolean onSender(final SenderConfig parent, final Sender sender) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSender(sender); + } + }); + } else { + parent.addSender(sender); + } + + return true; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..65887daa01 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxMaker.java @@ -0,0 +1,90 @@ +package com.dianping.cat.alarm.sender.transform; + +import static com.dianping.cat.alarm.sender.Constants.ATTR_BATCHSEND; +import static com.dianping.cat.alarm.sender.Constants.ATTR_ID; +import static com.dianping.cat.alarm.sender.Constants.ATTR_SUCCESSCODE; +import static com.dianping.cat.alarm.sender.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.sender.Constants.ATTR_URL; + +import org.xml.sax.Attributes; + +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Par buildPar(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Par par = new Par(); + + if (id != null) { + par.setId(id); + } + + return par; + } + + @Override + public Sender buildSender(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String url = attributes.getValue(ATTR_URL); + String type = attributes.getValue(ATTR_TYPE); + String successCode = attributes.getValue(ATTR_SUCCESSCODE); + String batchSend = attributes.getValue(ATTR_BATCHSEND); + Sender sender = new Sender(id); + + if (url != null) { + sender.setUrl(url); + } + + if (type != null) { + sender.setType(type); + } + + if (successCode != null) { + sender.setSuccessCode(successCode); + } + + if (batchSend != null) { + sender.setBatchSend(convert(Boolean.class, batchSend, false)); + } + + return sender; + } + + @Override + public SenderConfig buildSenderConfig(Attributes attributes) { + SenderConfig senderConfig = new SenderConfig(); + + return senderConfig; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..16f24eaf8b --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultSaxParser.java @@ -0,0 +1,250 @@ +package com.dianping.cat.alarm.sender.transform; + +import static com.dianping.cat.alarm.sender.Constants.ENTITY_PAR; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_SENDER; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_SENDER_CONFIG; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.alarm.sender.IEntity; +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static SenderConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(SenderConfig.class, new InputSource(removeBOM(in))); + } + + public static SenderConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(SenderConfig.class, new InputSource(removeBOM(reader))); + } + + public static SenderConfig parse(String xml) throws SAXException, IOException { + return parseEntity(SenderConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForPar(Par parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForSender(Sender parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PAR.equals(qName)) { + Par par = m_maker.buildPar(attributes); + + m_linker.onPar(parentObj, par); + m_objs.push(par); + } else { + throw new SAXException(String.format("Element(%s) is not expected under sender!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSenderConfig(SenderConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SENDER.equals(qName)) { + Sender sender = m_maker.buildSender(attributes); + + m_linker.onSender(parentObj, sender); + m_objs.push(sender); + } else { + throw new SAXException(String.format("Element(%s) is not expected under sender-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_SENDER_CONFIG.equals(qName)) { + SenderConfig senderConfig = m_maker.buildSenderConfig(attributes); + + m_entity = senderConfig; + m_objs.push(senderConfig); + m_tags.push(qName); + } else if (ENTITY_SENDER.equals(qName)) { + Sender sender = m_maker.buildSender(attributes); + + m_entity = sender; + m_objs.push(sender); + m_tags.push(qName); + } else if (ENTITY_PAR.equals(qName)) { + Par par = m_maker.buildPar(attributes); + + m_entity = par; + m_objs.push(par); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof SenderConfig) { + parseForSenderConfig((SenderConfig) parent, tag, qName, attributes); + } else if (parent instanceof Sender) { + parseForSender((Sender) parent, tag, qName, attributes); + } else if (parent instanceof Par) { + parseForPar((Par) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultXmlBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..991df210d5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/DefaultXmlBuilder.java @@ -0,0 +1,231 @@ +package com.dianping.cat.alarm.sender.transform; + +import static com.dianping.cat.alarm.sender.Constants.ATTR_BATCHSEND; +import static com.dianping.cat.alarm.sender.Constants.ATTR_ID; +import static com.dianping.cat.alarm.sender.Constants.ATTR_SUCCESSCODE; +import static com.dianping.cat.alarm.sender.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.sender.Constants.ATTR_URL; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_PAR; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_SENDER; +import static com.dianping.cat.alarm.sender.Constants.ENTITY_SENDER_CONFIG; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.alarm.sender.IEntity; +import com.dianping.cat.alarm.sender.IVisitor; +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitPar(Par par) { + startTag(ENTITY_PAR, true, null, ATTR_ID, par.getId()); + } + + @Override + public void visitSender(Sender sender) { + startTag(ENTITY_SENDER, null, ATTR_ID, sender.getId(), ATTR_URL, sender.getUrl(), ATTR_TYPE, sender.getType(), ATTR_SUCCESSCODE, sender.getSuccessCode(), ATTR_BATCHSEND, sender.isBatchSend()); + + if (!sender.getPars().isEmpty()) { + for (Par par : sender.getPars()) { + par.accept(m_visitor); + } + } + + endTag(ENTITY_SENDER); + } + + @Override + public void visitSenderConfig(SenderConfig senderConfig) { + startTag(ENTITY_SENDER_CONFIG, null); + + if (!senderConfig.getSenders().isEmpty()) { + for (Sender sender : senderConfig.getSenders().values()) { + sender.accept(m_visitor); + } + } + + endTag(ENTITY_SENDER_CONFIG); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/ILinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/ILinker.java new file mode 100644 index 0000000000..89898470b6 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.alarm.sender.transform; + +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public interface ILinker { + + public boolean onPar(Sender parent, Par par); + + public boolean onSender(SenderConfig parent, Sender sender); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IMaker.java new file mode 100644 index 0000000000..d28e40e5cf --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.alarm.sender.transform; + +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public interface IMaker { + + public Par buildPar(T node); + + public Sender buildSender(T node); + + public SenderConfig buildSenderConfig(T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IParser.java new file mode 100644 index 0000000000..cf01cca49b --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/sender/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.alarm.sender.transform; + +import com.dianping.cat.alarm.sender.entity.Par; +import com.dianping.cat.alarm.sender.entity.Sender; +import com.dianping.cat.alarm.sender.entity.SenderConfig; + +public interface IParser { + public SenderConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForPar(IMaker maker, ILinker linker, Par parent, T node); + + public void parseForSender(IMaker maker, ILinker linker, Sender parent, T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/BaseEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/BaseEntity.java new file mode 100644 index 0000000000..f665797d11 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/BaseEntity.java @@ -0,0 +1,56 @@ +package com.dianping.cat.alarm.server; + +import java.util.Formattable; +import java.util.FormattableFlags; +import java.util.Formatter; + +import com.dianping.cat.alarm.server.transform.DefaultXmlBuilder; +import com.dianping.cat.alarm.server.transform.DefaultJsonBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String JSON = "%#.3s"; + + public static final String JSON_COMPACT = "%#s"; + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean useJson = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE; + boolean compact = (precision <= 0); + + if (useJson) { + DefaultJsonBuilder builder = new DefaultJsonBuilder(compact); + + formatter.format("%s", builder.build(this)); + } else { + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/Constants.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/Constants.java new file mode 100644 index 0000000000..ac6da80602 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/Constants.java @@ -0,0 +1,34 @@ +package com.dianping.cat.alarm.server; + +public class Constants { + + public static final String ATTR_ALERT_TYPE = "alert-type"; + + public static final String ATTR_DURATION = "duration"; + + public static final String ATTR_END_TIME = "end-time"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_INTERVAL = "interval"; + + public static final String ATTR_START_TIME = "start-time"; + + public static final String ATTR_TYPE = "type"; + + public static final String ATTR_VALUE = "value"; + + public static final String ENTITY_CONDITION = "condition"; + + public static final String ENTITY_CONDITIONS = "conditions"; + + public static final String ENTITY_RULE = "rule"; + + public static final String ENTITY_RULES = "rules"; + + public static final String ENTITY_SERVER_ALARM_RULE_CONFIG = "server-alarm-rule-config"; + + public static final String ENTITY_SUB_CONDITION = "sub-condition"; + + public static final String ENTITY_SUB_CONDITIONS = "sub-conditions"; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IEntity.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IEntity.java new file mode 100644 index 0000000000..20cec87eb5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.alarm.server; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IVisitor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IVisitor.java new file mode 100644 index 0000000000..9030b4f862 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/IVisitor.java @@ -0,0 +1,17 @@ +package com.dianping.cat.alarm.server; + +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public interface IVisitor { + + public void visitCondition(Condition condition); + + public void visitRule(Rule rule); + + public void visitServerAlarmRuleConfig(ServerAlarmRuleConfig serverAlarmRuleConfig); + + public void visitSubCondition(SubCondition subCondition); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Condition.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Condition.java new file mode 100644 index 0000000000..d6e8a62759 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Condition.java @@ -0,0 +1,118 @@ +package com.dianping.cat.alarm.server.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.server.BaseEntity; +import com.dianping.cat.alarm.server.IVisitor; + +public class Condition extends BaseEntity { + private String m_interval; + + private int m_duration; + + private String m_alertType; + + private List m_subConditions = new ArrayList(); + + public Condition() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCondition(this); + } + + public Condition addSubCondition(SubCondition subCondition) { + m_subConditions.add(subCondition); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Condition) { + Condition _o = (Condition) obj; + + if (!equals(getInterval(), _o.getInterval())) { + return false; + } + + if (getDuration() != _o.getDuration()) { + return false; + } + + if (!equals(getAlertType(), _o.getAlertType())) { + return false; + } + + if (!equals(getSubConditions(), _o.getSubConditions())) { + return false; + } + + + return true; + } + + return false; + } + + public String getAlertType() { + return m_alertType; + } + + public int getDuration() { + return m_duration; + } + + public String getInterval() { + return m_interval; + } + + public List getSubConditions() { + return m_subConditions; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_interval == null ? 0 : m_interval.hashCode()); + hash = hash * 31 + m_duration; + hash = hash * 31 + (m_alertType == null ? 0 : m_alertType.hashCode()); + for (SubCondition e : m_subConditions) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + + return hash; + } + + @Override + public void mergeAttributes(Condition other) { + if (other.getInterval() != null) { + m_interval = other.getInterval(); + } + + m_duration = other.getDuration(); + + if (other.getAlertType() != null) { + m_alertType = other.getAlertType(); + } + } + + public Condition setAlertType(String alertType) { + m_alertType = alertType; + return this; + } + + public Condition setDuration(int duration) { + m_duration = duration; + return this; + } + + public Condition setInterval(String interval) { + m_interval = interval; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Rule.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Rule.java new file mode 100644 index 0000000000..35ef29b9e2 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/Rule.java @@ -0,0 +1,100 @@ +package com.dianping.cat.alarm.server.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.server.BaseEntity; +import com.dianping.cat.alarm.server.IVisitor; + +public class Rule extends BaseEntity { + private String m_startTime; + + private String m_endTime; + + private List m_conditions = new ArrayList(); + + public Rule() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRule(this); + } + + public Rule addCondition(Condition condition) { + m_conditions.add(condition); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Rule) { + Rule _o = (Rule) obj; + + if (!equals(getStartTime(), _o.getStartTime())) { + return false; + } + + if (!equals(getEndTime(), _o.getEndTime())) { + return false; + } + + if (!equals(getConditions(), _o.getConditions())) { + return false; + } + + + return true; + } + + return false; + } + + public List getConditions() { + return m_conditions; + } + + public String getEndTime() { + return m_endTime; + } + + public String getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_startTime == null ? 0 : m_startTime.hashCode()); + hash = hash * 31 + (m_endTime == null ? 0 : m_endTime.hashCode()); + for (Condition e : m_conditions) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + + return hash; + } + + @Override + public void mergeAttributes(Rule other) { + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Rule setEndTime(String endTime) { + m_endTime = endTime; + return this; + } + + public Rule setStartTime(String startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/ServerAlarmRuleConfig.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/ServerAlarmRuleConfig.java new file mode 100644 index 0000000000..1d41967be4 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/ServerAlarmRuleConfig.java @@ -0,0 +1,80 @@ +package com.dianping.cat.alarm.server.entity; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.alarm.server.BaseEntity; +import com.dianping.cat.alarm.server.IVisitor; + +public class ServerAlarmRuleConfig extends BaseEntity { + private String m_id; + + private List m_rules = new ArrayList(); + + public ServerAlarmRuleConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitServerAlarmRuleConfig(this); + } + + public ServerAlarmRuleConfig addRule(Rule rule) { + m_rules.add(rule); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ServerAlarmRuleConfig) { + ServerAlarmRuleConfig _o = (ServerAlarmRuleConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + if (!equals(getRules(), _o.getRules())) { + return false; + } + + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public List getRules() { + return m_rules; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + for (Rule e : m_rules) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + + return hash; + } + + @Override + public void mergeAttributes(ServerAlarmRuleConfig other) { + if (other.getId() != null) { + m_id = other.getId(); + } + } + + public ServerAlarmRuleConfig setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/SubCondition.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/SubCondition.java new file mode 100644 index 0000000000..9dab08ba5a --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/entity/SubCondition.java @@ -0,0 +1,78 @@ +package com.dianping.cat.alarm.server.entity; + +import com.dianping.cat.alarm.server.BaseEntity; +import com.dianping.cat.alarm.server.IVisitor; + +public class SubCondition extends BaseEntity { + private String m_type; + + private String m_value; + + public SubCondition() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSubCondition(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SubCondition) { + SubCondition _o = (SubCondition) obj; + + if (!equals(getType(), _o.getType())) { + return false; + } + + if (!equals(getValue(), _o.getValue())) { + return false; + } + + + return true; + } + + return false; + } + + public String getType() { + return m_type; + } + + public String getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_type == null ? 0 : m_type.hashCode()); + hash = hash * 31 + (m_value == null ? 0 : m_value.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(SubCondition other) { + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getValue() != null) { + m_value = other.getValue(); + } + } + + public SubCondition setType(String type) { + m_type = type; + return this; + } + + public SubCondition setValue(String value) { + m_value = value; + return this; + } + +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonBuilder.java new file mode 100644 index 0000000000..208ab6f85c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonBuilder.java @@ -0,0 +1,300 @@ +package com.dianping.cat.alarm.server.transform; + +import static com.dianping.cat.alarm.server.Constants.ATTR_ALERT_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_DURATION; +import static com.dianping.cat.alarm.server.Constants.ATTR_END_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_ID; +import static com.dianping.cat.alarm.server.Constants.ATTR_INTERVAL; +import static com.dianping.cat.alarm.server.Constants.ATTR_START_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_VALUE; +import static com.dianping.cat.alarm.server.Constants.ENTITY_CONDITIONS; +import static com.dianping.cat.alarm.server.Constants.ENTITY_RULES; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SUB_CONDITIONS; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + +import com.dianping.cat.alarm.server.IEntity; +import com.dianping.cat.alarm.server.IVisitor; +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultJsonBuilder implements IVisitor { + + private IVisitor m_visitor; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultJsonBuilder() { + this(false); + } + + public DefaultJsonBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultJsonBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_visitor = this; + } + + protected void arrayBegin(String name) { + indent(); + m_sb.append('"').append(name).append(m_compact ? "\":[" : "\": [\r\n"); + m_level++; + } + + protected void arrayEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append("],").append(m_compact ? "" : "\r\n"); + } + + protected void attributes(Map dynamicAttributes, Object... nameValues) { + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + if (attrValue instanceof Collection) { + @SuppressWarnings("unchecked") + Collection items = (Collection) attrValue; + + if (!items.isEmpty()) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (Object item : items) { + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else if (attrValue.getClass().isArray()) { + int length = Array.getLength(attrValue); + + if (length > 0) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (int j = 0; j < length; j++) { + Object item = Array.get(attrValue, j); + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else { + if (m_compact) { + m_sb.append('"').append(attrName).append("\":"); + toString(m_sb, attrValue); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(attrName).append("\": "); + toString(m_sb, attrValue); + m_sb.append(",\r\n"); + } + } + } + } + + if (dynamicAttributes != null) { + for (Map.Entry e : dynamicAttributes.entrySet()) { + if (m_compact) { + m_sb.append('"').append(e.getKey()).append("\":"); + toString(m_sb, e.getValue()); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(e.getKey()).append("\": "); + toString(m_sb, e.getValue()); + m_sb.append(",\r\n"); + } + } + } + } + + public String build(IEntity entity) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + trimComma(); + + return m_sb.toString(); + } + + public String buildArray(Collection> entities) { + m_sb.append('['); + + if (entities != null) { + for (IEntity entity : entities) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + } + + trimComma(); + } + + m_sb.append(']'); + + return m_sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void objectBegin(String name) { + indent(); + + if (name == null) { + m_sb.append("{").append(m_compact ? "" : "\r\n"); + } else { + m_sb.append('"').append(name).append(m_compact ? "\":{" : "\": {\r\n"); + } + + m_level++; + } + + protected void objectEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append(m_compact ? "}," : "},\r\n"); + } + + protected void toString(StringBuilder sb, Object value) { + if (value == null) { + sb.append("null"); + } else if (value instanceof Boolean || value instanceof Number) { + sb.append(value); + } else { + String val = value.toString(); + int len = val.length(); + + sb.append('"'); + + for (int i = 0; i < len; i++) { + char ch = val.charAt(i); + + switch (ch) { + case '\\': + case '/': + case '"': + sb.append('\\').append(ch); + break; + case '\t': + sb.append("\\t"); + break; + case '\r': + sb.append("\\r"); + break; + case '\n': + sb.append("\\n"); + break; + default: + sb.append(ch); + break; + } + } + + sb.append('"'); + } + } + + protected void trimComma() { + int len = m_sb.length(); + + if (m_compact) { + if (len > 1 && m_sb.charAt(len - 1) == ',') { + m_sb.replace(len - 1, len, ""); + } + } else { + if (len > 3 && m_sb.charAt(len - 3) == ',') { + m_sb.replace(len - 3, len - 2, ""); + } + } + } + + @Override + public void visitCondition(Condition condition) { + attributes(null, ATTR_INTERVAL, condition.getInterval(), ATTR_DURATION, condition.getDuration(), ATTR_ALERT_TYPE, condition.getAlertType()); + + if (!condition.getSubConditions().isEmpty()) { + arrayBegin(ENTITY_SUB_CONDITIONS); + + for (SubCondition subCondition : condition.getSubConditions()) { + objectBegin(null); + subCondition.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_SUB_CONDITIONS); + } + } + + @Override + public void visitRule(Rule rule) { + attributes(null, ATTR_START_TIME, rule.getStartTime(), ATTR_END_TIME, rule.getEndTime()); + + if (!rule.getConditions().isEmpty()) { + arrayBegin(ENTITY_CONDITIONS); + + for (Condition condition : rule.getConditions()) { + objectBegin(null); + condition.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_CONDITIONS); + } + } + + @Override + public void visitServerAlarmRuleConfig(ServerAlarmRuleConfig serverAlarmRuleConfig) { + attributes(null, ATTR_ID, serverAlarmRuleConfig.getId()); + + if (!serverAlarmRuleConfig.getRules().isEmpty()) { + arrayBegin(ENTITY_RULES); + + for (Rule rule : serverAlarmRuleConfig.getRules()) { + objectBegin(null); + rule.accept(m_visitor); + objectEnd(null); + } + + arrayEnd(ENTITY_RULES); + } + } + + @Override + public void visitSubCondition(SubCondition subCondition) { + attributes(null, ATTR_TYPE, subCondition.getType(), ATTR_VALUE, subCondition.getValue()); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonParser.java new file mode 100644 index 0000000000..2b0e35e8f5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultJsonParser.java @@ -0,0 +1,426 @@ +package com.dianping.cat.alarm.server.transform; + +import static com.dianping.cat.alarm.server.Constants.ATTR_ALERT_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_DURATION; +import static com.dianping.cat.alarm.server.Constants.ATTR_END_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_ID; +import static com.dianping.cat.alarm.server.Constants.ATTR_INTERVAL; +import static com.dianping.cat.alarm.server.Constants.ATTR_START_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_VALUE; +import static com.dianping.cat.alarm.server.Constants.ENTITY_CONDITIONS; +import static com.dianping.cat.alarm.server.Constants.ENTITY_RULES; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SUB_CONDITIONS; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.dianping.cat.alarm.server.IEntity; +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultJsonParser { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private List m_entities = new ArrayList(); + + private Class m_entityClass; + + private DefaultJsonParser(Class entityClass) { + m_entityClass = entityClass; + } + + public static > T parse(Class entityClass, InputStream in) throws IOException { + return parse(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > T parse(Class entityClass, Reader reader) throws IOException { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.onArrayBegin(); + parser.parse(new JsonReader(reader)); + parser.onArrayEnd(); + + if (parser.m_entities.isEmpty()) { + return null; + } else { + return (T) parser.m_entities.get(0); + } + } + + public static > T parse(Class entityClass, String json) throws IOException { + return parse(entityClass, new StringReader(json)); + } + + public static > List parseArray(Class entityClass, InputStream in) throws Exception { + return parseArray(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > List parseArray(Class entityClass, Reader reader) throws Exception { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.parse(new JsonReader(reader)); + return (List) (List) parser.m_entities; + } + + public static > List parseArray(Class entityClass, String json) throws Exception { + return parseArray(entityClass, new StringReader(json)); + } + + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + private Object createRootEntity() { + try { + Object entity = m_entityClass.newInstance(); + + return entity; + } catch (Exception e) { + throw new RuntimeException(String.format("Unable to create entity(%s) instance!", m_entityClass.getName()), e); + } + } + + private boolean isTopLevel() { + return m_objs.size() == 1; + } + + protected void onArrayBegin() { + if (m_objs.isEmpty()) { + m_objs.push(m_entities); + m_tags.push(""); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ServerAlarmRuleConfig) { + if (ENTITY_RULES.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else if (parent instanceof Rule) { + if (ENTITY_CONDITIONS.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else if (parent instanceof Condition) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + m_objs.push(parent); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } } + + protected void onArrayEnd() { + m_objs.pop(); + m_tags.pop(); + + } + protected void onName(String name) { + m_tags.push(name); + } + + protected void onObjectBegin() { + if (isTopLevel()) { + m_objs.push(createRootEntity()); + m_tags.push(""); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ServerAlarmRuleConfig) { + if (ENTITY_RULES.equals(tag)) { + Rule rules = new Rule(); + + m_linker.onRule((ServerAlarmRuleConfig) parent, rules); + m_objs.push(rules); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else if (parent instanceof Rule) { + if (ENTITY_CONDITIONS.equals(tag)) { + Condition conditions = new Condition(); + + m_linker.onCondition((Rule) parent, conditions); + m_objs.push(conditions); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else if (parent instanceof Condition) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + SubCondition subConditions = new SubCondition(); + + m_linker.onSubCondition((Condition) parent, subConditions); + m_objs.push(subConditions); + m_tags.push(""); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); /// + } + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } + } + + protected void onObjectEnd() { + m_tags.pop(); + + Object entity = m_objs.pop(); + + if (isTopLevel()) { + m_entities.add(entity); + } + } + + protected void onValue(String value) { + Object parent = m_objs.peek(); + String tag = m_tags.pop(); + + if (parent instanceof ServerAlarmRuleConfig) { + parseForServerAlarmRuleConfig((ServerAlarmRuleConfig) parent, tag, value); + } else if (parent instanceof Rule) { + parseForRule((Rule) parent, tag, value); + } else if (parent instanceof Condition) { + parseForCondition((Condition) parent, tag, value); + } else if (parent instanceof SubCondition) { + parseForSubCondition((SubCondition) parent, tag, value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) under %s!", tag, parent)); + } + } + + private void parse(JsonReader reader) throws IOException { + try { + reader.parse(this); + } catch (EOFException e) { + if (m_objs.size() > 1) { + throw new EOFException(String.format("Unexpected end while parsing json! tags: %s.", m_tags)); + } + } + + m_linker.finish(); + } + + public void parseForCondition(Condition condition, String tag, String value) { + if (ENTITY_SUB_CONDITIONS.equals(tag)) { + // do nothing here + } else if (ATTR_INTERVAL.equals(tag)) { + condition.setInterval(value); + } else if (ATTR_DURATION.equals(tag)) { + condition.setDuration(convert(Integer.class, value, 0)); + } else if (ATTR_ALERT_TYPE.equals(tag)) { + condition.setAlertType(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, condition, m_tags)); + } + } + + public void parseForRule(Rule rule, String tag, String value) { + if (ENTITY_CONDITIONS.equals(tag)) { + // do nothing here + } else if (ATTR_START_TIME.equals(tag)) { + rule.setStartTime(value); + } else if (ATTR_END_TIME.equals(tag)) { + rule.setEndTime(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, rule, m_tags)); + } + } + + public void parseForServerAlarmRuleConfig(ServerAlarmRuleConfig serverAlarmRuleConfig, String tag, String value) { + if (ENTITY_RULES.equals(tag)) { + // do nothing here + } else if (ATTR_ID.equals(tag)) { + serverAlarmRuleConfig.setId(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, serverAlarmRuleConfig, m_tags)); + } + } + + public void parseForSubCondition(SubCondition subCondition, String tag, String value) { + if (ATTR_TYPE.equals(tag)) { + subCondition.setType(value); + } else if (ATTR_VALUE.equals(tag)) { + subCondition.setValue(value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, subCondition, m_tags)); + } + } + + + static class JsonReader { + private Reader m_reader; + + private char[] m_buffer = new char[2048]; + + private int m_size; + + private int m_index; + + public JsonReader(Reader reader) { + m_reader = reader; + } + + private char next() throws IOException { + if (m_index >= m_size) { + m_size = m_reader.read(m_buffer); + m_index = 0; + + if (m_size == -1) { + throw new EOFException(); + } + } + + return m_buffer[m_index++]; + } + + public void parse(DefaultJsonParser parser) throws IOException { + StringBuilder sb = new StringBuilder(); + boolean flag = false; + + while (true) { + char ch = next(); + + switch (ch) { + case ' ': + case '\t': + case '\r': + case '\n': + break; + case '{': + parser.onObjectBegin(); + flag = false; + break; + case '}': + if (flag) { // have value + parser.onValue(sb.toString()); + sb.setLength(0); + } + + parser.onObjectEnd(); + flag = false; + break; + case '\'': + case '"': + while (true) { + char ch2 = next(); + + if (ch2 != ch) { + if (ch2 == '\\') { + char ch3 = next(); + + switch (ch3) { + case 't': + sb.append('\t'); + break; + case 'r': + sb.append('\r'); + break; + case 'n': + sb.append('\n'); + break; + default: + sb.append(ch3); + break; + } + } else { + sb.append(ch2); + } + } else { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + flag = false; + } + + sb.setLength(0); + break; + } + } + + break; + case ':': + if (sb.length() != 0) { + parser.onName(sb.toString()); + sb.setLength(0); + } + + flag = true; + break; + case ',': + if (sb.length() != 0) { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + } + + sb.setLength(0); + } + + flag = false; + break; + case '[': + parser.onArrayBegin(); + flag = false; + break; + case ']': + parser.onArrayEnd(); + flag = false; + break; + default: + sb.append(ch); + break; + } + } + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultLinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultLinker.java new file mode 100644 index 0000000000..93c0ffe466 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultLinker.java @@ -0,0 +1,43 @@ +package com.dianping.cat.alarm.server.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultLinker implements ILinker { + @SuppressWarnings("unused") + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onCondition(final Rule parent, final Condition condition) { + parent.addCondition(condition); + return true; + } + + @Override + public boolean onRule(final ServerAlarmRuleConfig parent, final Rule rule) { + parent.addRule(rule); + return true; + } + + @Override + public boolean onSubCondition(final Condition parent, final SubCondition subCondition) { + parent.addSubCondition(subCondition); + return true; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..c92b031d64 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxMaker.java @@ -0,0 +1,115 @@ +package com.dianping.cat.alarm.server.transform; + +import static com.dianping.cat.alarm.server.Constants.ATTR_ALERT_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_DURATION; +import static com.dianping.cat.alarm.server.Constants.ATTR_END_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_ID; +import static com.dianping.cat.alarm.server.Constants.ATTR_INTERVAL; +import static com.dianping.cat.alarm.server.Constants.ATTR_START_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_VALUE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Condition buildCondition(Attributes attributes) { + String interval = attributes.getValue(ATTR_INTERVAL); + String duration = attributes.getValue(ATTR_DURATION); + String alertType = attributes.getValue(ATTR_ALERT_TYPE); + Condition condition = new Condition(); + + if (interval != null) { + condition.setInterval(interval); + } + + if (duration != null) { + condition.setDuration(convert(Integer.class, duration, 0)); + } + + if (alertType != null) { + condition.setAlertType(alertType); + } + + return condition; + } + + @Override + public Rule buildRule(Attributes attributes) { + String startTime = attributes.getValue(ATTR_START_TIME); + String endTime = attributes.getValue(ATTR_END_TIME); + Rule rule = new Rule(); + + if (startTime != null) { + rule.setStartTime(startTime); + } + + if (endTime != null) { + rule.setEndTime(endTime); + } + + return rule; + } + + @Override + public ServerAlarmRuleConfig buildServerAlarmRuleConfig(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + ServerAlarmRuleConfig serverAlarmRuleConfig = new ServerAlarmRuleConfig(); + + if (id != null) { + serverAlarmRuleConfig.setId(id); + } + + return serverAlarmRuleConfig; + } + + @Override + public SubCondition buildSubCondition(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String value = attributes.getValue(ATTR_VALUE); + SubCondition subCondition = new SubCondition(); + + if (type != null) { + subCondition.setType(type); + } + + if (value != null) { + subCondition.setValue(value); + } + + return subCondition; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..f0bfda282b --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultSaxParser.java @@ -0,0 +1,273 @@ +package com.dianping.cat.alarm.server.transform; + +import static com.dianping.cat.alarm.server.Constants.ENTITY_CONDITION; +import static com.dianping.cat.alarm.server.Constants.ENTITY_RULE; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SERVER_ALARM_RULE_CONFIG; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SUB_CONDITION; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.alarm.server.IEntity; +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static ServerAlarmRuleConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(ServerAlarmRuleConfig.class, new InputSource(removeBOM(in))); + } + + public static ServerAlarmRuleConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(ServerAlarmRuleConfig.class, new InputSource(removeBOM(reader))); + } + + public static ServerAlarmRuleConfig parse(String xml) throws SAXException, IOException { + return parseEntity(ServerAlarmRuleConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForCondition(Condition parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SUB_CONDITION.equals(qName)) { + SubCondition subCondition = m_maker.buildSubCondition(attributes); + + m_linker.onSubCondition(parentObj, subCondition); + m_objs.push(subCondition); + } else { + throw new SAXException(String.format("Element(%s) is not expected under condition!", qName)); + } + + m_tags.push(qName); + } + + private void parseForRule(Rule parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_CONDITION.equals(qName)) { + Condition condition = m_maker.buildCondition(attributes); + + m_linker.onCondition(parentObj, condition); + m_objs.push(condition); + } else { + throw new SAXException(String.format("Element(%s) is not expected under rule!", qName)); + } + + m_tags.push(qName); + } + + private void parseForServerAlarmRuleConfig(ServerAlarmRuleConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_RULE.equals(qName)) { + Rule rule = m_maker.buildRule(attributes); + + m_linker.onRule(parentObj, rule); + m_objs.push(rule); + } else { + throw new SAXException(String.format("Element(%s) is not expected under server-alarm-rule-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSubCondition(SubCondition parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_SERVER_ALARM_RULE_CONFIG.equals(qName)) { + ServerAlarmRuleConfig serverAlarmRuleConfig = m_maker.buildServerAlarmRuleConfig(attributes); + + m_entity = serverAlarmRuleConfig; + m_objs.push(serverAlarmRuleConfig); + m_tags.push(qName); + } else if (ENTITY_RULE.equals(qName)) { + Rule rule = m_maker.buildRule(attributes); + + m_entity = rule; + m_objs.push(rule); + m_tags.push(qName); + } else if (ENTITY_CONDITION.equals(qName)) { + Condition condition = m_maker.buildCondition(attributes); + + m_entity = condition; + m_objs.push(condition); + m_tags.push(qName); + } else if (ENTITY_SUB_CONDITION.equals(qName)) { + SubCondition subCondition = m_maker.buildSubCondition(attributes); + + m_entity = subCondition; + m_objs.push(subCondition); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ServerAlarmRuleConfig) { + parseForServerAlarmRuleConfig((ServerAlarmRuleConfig) parent, tag, qName, attributes); + } else if (parent instanceof Rule) { + parseForRule((Rule) parent, tag, qName, attributes); + } else if (parent instanceof Condition) { + parseForCondition((Condition) parent, tag, qName, attributes); + } else if (parent instanceof SubCondition) { + parseForSubCondition((SubCondition) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultXmlBuilder.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..514f973cf5 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/DefaultXmlBuilder.java @@ -0,0 +1,249 @@ +package com.dianping.cat.alarm.server.transform; + +import static com.dianping.cat.alarm.server.Constants.ATTR_ALERT_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_DURATION; +import static com.dianping.cat.alarm.server.Constants.ATTR_END_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_ID; +import static com.dianping.cat.alarm.server.Constants.ATTR_INTERVAL; +import static com.dianping.cat.alarm.server.Constants.ATTR_START_TIME; +import static com.dianping.cat.alarm.server.Constants.ATTR_TYPE; +import static com.dianping.cat.alarm.server.Constants.ATTR_VALUE; +import static com.dianping.cat.alarm.server.Constants.ENTITY_CONDITION; +import static com.dianping.cat.alarm.server.Constants.ENTITY_RULE; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SERVER_ALARM_RULE_CONFIG; +import static com.dianping.cat.alarm.server.Constants.ENTITY_SUB_CONDITION; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.alarm.server.IEntity; +import com.dianping.cat.alarm.server.IVisitor; +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitCondition(Condition condition) { + startTag(ENTITY_CONDITION, null, ATTR_INTERVAL, condition.getInterval(), ATTR_DURATION, condition.getDuration(), ATTR_ALERT_TYPE, condition.getAlertType()); + + if (!condition.getSubConditions().isEmpty()) { + for (SubCondition subCondition : condition.getSubConditions()) { + subCondition.accept(m_visitor); + } + } + + endTag(ENTITY_CONDITION); + } + + @Override + public void visitRule(Rule rule) { + startTag(ENTITY_RULE, null, ATTR_START_TIME, rule.getStartTime(), ATTR_END_TIME, rule.getEndTime()); + + if (!rule.getConditions().isEmpty()) { + for (Condition condition : rule.getConditions()) { + condition.accept(m_visitor); + } + } + + endTag(ENTITY_RULE); + } + + @Override + public void visitServerAlarmRuleConfig(ServerAlarmRuleConfig serverAlarmRuleConfig) { + startTag(ENTITY_SERVER_ALARM_RULE_CONFIG, null, ATTR_ID, serverAlarmRuleConfig.getId()); + + if (!serverAlarmRuleConfig.getRules().isEmpty()) { + for (Rule rule : serverAlarmRuleConfig.getRules()) { + rule.accept(m_visitor); + } + } + + endTag(ENTITY_SERVER_ALARM_RULE_CONFIG); + } + + @Override + public void visitSubCondition(SubCondition subCondition) { + startTag(ENTITY_SUB_CONDITION, true, null, ATTR_TYPE, subCondition.getType(), ATTR_VALUE, subCondition.getValue()); + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/ILinker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/ILinker.java new file mode 100644 index 0000000000..4931283c40 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/ILinker.java @@ -0,0 +1,15 @@ +package com.dianping.cat.alarm.server.transform; + +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public interface ILinker { + + public boolean onCondition(Rule parent, Condition condition); + + public boolean onRule(ServerAlarmRuleConfig parent, Rule rule); + + public boolean onSubCondition(Condition parent, SubCondition subCondition); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IMaker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IMaker.java new file mode 100644 index 0000000000..958f1caa19 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IMaker.java @@ -0,0 +1,17 @@ +package com.dianping.cat.alarm.server.transform; + +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public interface IMaker { + + public Condition buildCondition(T node); + + public Rule buildRule(T node); + + public ServerAlarmRuleConfig buildServerAlarmRuleConfig(T node); + + public SubCondition buildSubCondition(T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IParser.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IParser.java new file mode 100644 index 0000000000..fd20b5d359 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/server/transform/IParser.java @@ -0,0 +1,16 @@ +package com.dianping.cat.alarm.server.transform; + +import com.dianping.cat.alarm.server.entity.Condition; +import com.dianping.cat.alarm.server.entity.Rule; +import com.dianping.cat.alarm.server.entity.ServerAlarmRuleConfig; +import com.dianping.cat.alarm.server.entity.SubCondition; + +public interface IParser { + public ServerAlarmRuleConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForCondition(IMaker maker, ILinker linker, Condition parent, T node); + + public void parseForRule(IMaker maker, ILinker linker, Rule parent, T node); + + public void parseForSubCondition(IMaker maker, ILinker linker, SubCondition parent, T node); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/service/AlertService.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/service/AlertService.java index 58a3bfa92b..7b2e0aa80a 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/service/AlertService.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/service/AlertService.java @@ -22,22 +22,20 @@ import java.util.LinkedList; import java.util.List; -import org.unidal.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.Alert; -import com.dianping.cat.alarm.AlertDao; import com.dianping.cat.alarm.spi.AlertEntity; import com.dianping.cat.alarm.spi.sender.SendMessageEntity; +import com.dianping.cat.mybatis.repository.alert.AlertRepository; -@Named public class AlertService { + private static final Logger LOGGER = LoggerFactory.getLogger(AlertService.class); - @Inject - private AlertDao m_alertDao; + private AlertRepository m_alertDao; private Alert buildAlert(AlertEntity alertEntity, SendMessageEntity message) { Alert alert = new Alert(); @@ -56,11 +54,11 @@ public List query(Date start, Date end, String type) { List alerts = new LinkedList(); try { - alerts = m_alertDao.queryAlertsByTimeCategory(start, end, type, - com.dianping.cat.alarm.AlertEntity.READSET_FULL); - } catch (DalNotFoundException e) { + alerts = m_alertDao.queryAlertsByTimeCategory(start, end, type); + } catch (EmptyResultDataAccessException e) { // ignore } catch (Exception e) { + LOGGER.error("Unable to query alerts, start={}, end={}, type={}.", start, end, type, e); Cat.logError(e); } @@ -74,10 +72,18 @@ public void insert(AlertEntity alertEntity, SendMessageEntity message) { int count = m_alertDao.insert(alert); if (count != 1) { + LOGGER.error("Unexpected alert insert count, count={}, domain={}, category={}, metric={}.", count, + alert.getDomain(), alert.getCategory(), alert.getMetric()); Cat.logError("insert alert error: " + alert.toString(), new RuntimeException()); } - } catch (DalException e) { + } catch (RuntimeException e) { + LOGGER.error("Unable to insert alert, domain={}, type={}, metric={}.", alertEntity.getDomain(), + alertEntity.getType().getName(), alertEntity.getMetric(), e); Cat.logError(e); } } + + public void setAlertDao(AlertRepository alertDao) { + m_alertDao = alertDao; + } } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/AlertManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/AlertManager.java index 6b4ec81784..e6515af244 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/AlertManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/AlertManager.java @@ -29,13 +29,11 @@ import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.message.Event; -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 org.unidal.lookup.annotation.Named; -import org.unidal.tuple.Pair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads; +import com.dianping.cat.support.Threads.Task; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -47,30 +45,25 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -@Named -public class AlertManager implements Initializable { +public class AlertManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AlertManager.class); private static final int MILLIS1MINUTE = 60 * 1000; - @Inject + private volatile boolean m_initialized; + protected SpliterManager m_splitterManager; - @Inject protected SenderManager m_senderManager; - @Inject protected AlertService m_alertService; - @Inject private AlertPolicyManager m_policyManager; - @Inject private DecoratorManager m_decoratorManager; - @Inject private ContactorManager m_contactorManager; - @Inject private ServerConfigManager m_configManager; private BlockingQueue m_alerts = new LinkedBlockingDeque(10000); @@ -82,22 +75,43 @@ public class AlertManager implements Initializable { private ConcurrentHashMap m_alertMap = new ConcurrentHashMap(); public boolean addAlert(AlertEntity entity) { + ensureInitialized(); + m_alertMap.put(entity, entity.getDate().getTime()); String group = entity.getGroup(); Cat.logEvent("Alert:" + entity.getType().getName(), group, Event.SUCCESS, entity.toString()); if (m_configManager.isAlertMachine()) { - return m_alerts.offer(entity); + boolean offered = m_alerts.offer(entity); + + if (!offered) { + LOGGER.warn("Alert queue is full, alert is dropped, type={}, group={}, metric={}, key={}.", + entity.getType().getName(), group, entity.getMetric(), entity.getKey()); + } + return offered; } else { + LOGGER.info("Current machine is not configured as alert machine, skip queueing alert, type={}, group={}, key={}.", + entity.getType().getName(), group, entity.getKey()); return true; } } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + + LOGGER.info("Initializing alert manager executors."); Threads.forGroup("Cat").start(new SendExecutor()); Threads.forGroup("Cat").start(new RecoveryAnnouncer()); + m_initialized = true; } public boolean isSuspend(String alertKey, int suspendMinute) { @@ -107,6 +121,8 @@ public boolean isSuspend(String alertKey, int suspendMinute) { long duration = System.currentTimeMillis() - sendedAlert.getDate().getTime(); if (duration / MILLIS1MINUTE < suspendMinute) { + LOGGER.info("Alert is suspended, key={}, suspendMinute={}, elapsedMinute={}.", alertKey, suspendMinute, + duration / MILLIS1MINUTE); Cat.logEvent("SuspendAlert", alertKey, Event.SUCCESS, null); return true; } @@ -114,6 +130,34 @@ public boolean isSuspend(String alertKey, int suspendMinute) { return false; } + public void setAlertService(AlertService alertService) { + m_alertService = alertService; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + + public void setContactorManager(ContactorManager contactorManager) { + m_contactorManager = contactorManager; + } + + public void setDecoratorManager(DecoratorManager decoratorManager) { + m_decoratorManager = decoratorManager; + } + + public void setPolicyManager(AlertPolicyManager policyManager) { + m_policyManager = policyManager; + } + + public void setSenderManager(SenderManager senderManager) { + m_senderManager = senderManager; + } + + public void setSplitterManager(SpliterManager splitterManager) { + m_splitterManager = splitterManager; + } + public List queryLastestAlarmKey(int minute) { List keys = new ArrayList(); long currentTimeMillis = System.currentTimeMillis(); @@ -178,8 +222,15 @@ private boolean send(AlertEntity alert) { if (m_senderManager.sendAlert(channel, message)) { result = true; + LOGGER.info("Sent alert message, type={}, group={}, level={}, channel={}, receivers={}.", type, + group, level, channel, receivers.size()); + } else { + LOGGER.warn("Alert sender returned false, type={}, group={}, level={}, channel={}, receivers={}.", + type, group, level, channel, receivers.size()); } } else { + LOGGER.warn("No alert receiver found, type={}, group={}, contactGroup={}, channel={}.", type, group, + contactGroup, channel); Cat.logEvent("NoneReceiver:" + channel, type + ":" + contactGroup, Event.SUCCESS, null); } } @@ -212,8 +263,16 @@ private boolean sendRecoveryMessage(AlertEntity alert, String currentMinute) { SendMessageEntity message = new SendMessageEntity(group, title, type, content, receivers); if (m_senderManager.sendAlert(channel, message)) { + LOGGER.info("Sent alert recovery message, type={}, group={}, level={}, channel={}, receivers={}.", + type, group, level, channel, receivers.size()); return true; + } else { + LOGGER.warn("Alert recovery sender returned false, type={}, group={}, level={}, channel={}, receivers={}.", + type, group, level, channel, receivers.size()); } + } else { + LOGGER.warn("No alert recovery receiver found, type={}, group={}, contactGroup={}, channel={}.", type, + group, alert.getContactGroup(), channel); } } @@ -257,6 +316,7 @@ public void run() { sendRecoveryMessage(alert, currentStr); } } catch (Exception e) { + LOGGER.error("Unable to announce alert recovery, key={}.", entry.getKey(), e); Cat.logError(e); } } @@ -272,7 +332,10 @@ public void run() { try { TimeUnit.MILLISECONDS.sleep(lackMills); } catch (InterruptedException e) { + LOGGER.warn("Alert recovery announcer interrupted."); + Thread.currentThread().interrupt(); Cat.logError(e); + break; } } } @@ -299,8 +362,8 @@ public void run() { send(alert); } } catch (Exception e) { + LOGGER.error("Unable to process alert from queue.", e); Cat.logError(e); - e.printStackTrace(); } } } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertConfigManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertConfigManager.java index d5eaa9fe90..96af390483 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertConfigManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertConfigManager.java @@ -18,12 +18,10 @@ */ package com.dianping.cat.alarm.spi.config; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; -import org.unidal.lookup.util.StringUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.receiver.entity.AlertConfig; @@ -31,24 +29,31 @@ import com.dianping.cat.alarm.receiver.transform.DefaultSaxParser; import com.dianping.cat.config.content.ContentFetcher; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; -@Named -public class AlertConfigManager implements Initializable { +public class AlertConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AlertConfigManager.class); private static final String CONFIG_NAME = "alertConfig"; - @Inject - private ConfigDao m_configDao; + private ConfigRepository m_configDao; - @Inject private ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private AlertConfig m_config; + private volatile boolean m_initialized; + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + public String buildReceiverContentByOnOff(String originXml, String allOnOrOff) { try { if (StringUtils.isEmpty(allOnOrOff)) { @@ -65,57 +70,83 @@ public String buildReceiverContentByOnOff(String originXml, String allOnOrOff) { return tmpConfig.toString(); } catch (Exception e) { + LOGGER.error("Unable to build alert receiver config by onOff={}.", allOnOrOff, e); Cat.logError(e); return null; } } public AlertConfig getAlertConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { - try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); - String content = config.getContent(); - - m_configId = config.getId(); - m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } try { - String content = m_fetcher.getConfigContent(CONFIG_NAME); - Config config = m_configDao.createLocal(); - - config.setName(CONFIG_NAME); - config.setContent(content); - m_configDao.insert(config); + Config config = m_configDao.findByName(CONFIG_NAME); + String content = config.getContent(); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); - } catch (Exception ex) { - Cat.logError(ex); + LOGGER.info("Loaded alert config from repository, configId={}.", m_configId); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Alert config is missing in repository, loading default content from fetcher.", e); + + try { + String content = m_fetcher.getConfigContent(CONFIG_NAME); + Config config = m_configDao.createLocal(); + + config.setName(CONFIG_NAME); + config.setContent(content); + m_configDao.insert(config); + + m_configId = config.getId(); + m_config = DefaultSaxParser.parse(content); + LOGGER.info("Initialized alert config from default content, configId={}.", m_configId); + } catch (Exception ex) { + LOGGER.error("Unable to initialize alert config from default content.", ex); + Cat.logError(ex); + } + } catch (Exception e) { + LOGGER.error("Unable to load alert config from repository.", e); + Cat.logError(e); } - } catch (Exception e) { - Cat.logError(e); + if (m_config == null) { + m_config = new AlertConfig(); + LOGGER.warn("Alert config is empty after initialization, using a new empty config."); + } + m_initialized = true; } - if (m_config == null) { - m_config = new AlertConfig(); + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); } } public boolean insert(String xml) { + ensureInitialized(); try { m_config = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse alert config xml for insert. xmlLength={}.", xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } } public Receiver queryReceiverById(String id) { + ensureInitialized(); return m_config.getReceivers().get(id); } @@ -128,8 +159,11 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored alert config, configId={}, receiverCount={}.", m_configId, + m_config.getReceivers().size()); } catch (Exception e) { + LOGGER.error("Unable to store alert config, configId={}.", m_configId, e); Cat.logError(e); return false; } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertPolicyManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertPolicyManager.java index 6d784f4fa1..ba7e620ef9 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertPolicyManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/AlertPolicyManager.java @@ -21,11 +21,9 @@ import java.util.ArrayList; import java.util.List; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.policy.entity.AlertPolicy; @@ -36,11 +34,10 @@ import com.dianping.cat.alarm.spi.AlertChannel; import com.dianping.cat.config.content.ContentFetcher; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; -@Named -public class AlertPolicyManager implements Initializable { +public class AlertPolicyManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AlertPolicyManager.class); private static final String CONFIG_NAME = "alertPolicy"; @@ -48,62 +45,95 @@ public class AlertPolicyManager implements Initializable { private static final String DEFAULT_GROUP = "default"; - @Inject - private ConfigDao m_configDao; + private ConfigRepository m_configDao; - @Inject private ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private AlertPolicy m_config; + private volatile boolean m_initialized; + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + public AlertPolicy getAlertPolicy() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { - try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); - String content = config.getContent(); - - m_configId = config.getId(); - m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } try { - String content = m_fetcher.getConfigContent(CONFIG_NAME); - Config config = m_configDao.createLocal(); - - config.setName(CONFIG_NAME); - config.setContent(content); - m_configDao.insert(config); + Config config = m_configDao.findByName(CONFIG_NAME); + String content = config.getContent(); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); - } catch (Exception ex) { - Cat.logError(ex); + LOGGER.info("Loaded alert policy from repository, configId={}.", m_configId); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Alert policy is missing in repository, loading default content from fetcher.", e); + + try { + String content = m_fetcher.getConfigContent(CONFIG_NAME); + Config config = m_configDao.createLocal(); + + config.setName(CONFIG_NAME); + config.setContent(content); + m_configDao.insert(config); + + m_configId = config.getId(); + m_config = DefaultSaxParser.parse(content); + LOGGER.info("Initialized alert policy from default content, configId={}.", m_configId); + } catch (Exception ex) { + LOGGER.error("Unable to initialize alert policy from default content.", ex); + Cat.logError(ex); + } + } catch (Exception e) { + LOGGER.error("Unable to load alert policy from repository.", e); + Cat.logError(e); } - } catch (Exception e) { - Cat.logError(e); + if (m_config == null) { + m_config = new AlertPolicy(); + LOGGER.warn("Alert policy is empty after initialization, using a new empty policy."); + } + m_initialized = true; } - if (m_config == null) { - m_config = new AlertPolicy(); + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); } } public boolean insert(String xml) { + ensureInitialized(); try { m_config = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse alert policy xml for insert. xmlLength={}.", xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } } public List queryChannels(String typeName, String groupName, String levelName) { + ensureInitialized(); try { Level level = queryLevel(typeName, groupName, levelName); if (level == null) { @@ -121,14 +151,17 @@ public List queryChannels(String typeName, String groupName, Strin } } - return channels; - } - } catch (Exception ex) { - return new ArrayList(); + return channels; } + } catch (Exception ex) { + LOGGER.warn("Unable to query alert channels, type={}, group={}, level={}; returning empty channels.", typeName, + groupName, levelName, ex); + return new ArrayList(); } +} private Level queryLevel(String typeName, String groupName, String levelName) { + ensureInitialized(); Type type = m_config.findType(typeName); if (type == null) { @@ -145,32 +178,38 @@ private Level queryLevel(String typeName, String groupName, String levelName) { } public int queryRecoverMinute(String typeName, String groupName, String levelName) { + ensureInitialized(); try { Level level = queryLevel(typeName, groupName, levelName); if (level == null) { return 1; } else { - return level.getRecoverMinute(); - } - } catch (Exception ex) { - return 1; + return level.getRecoverMinute(); } + } catch (Exception ex) { + LOGGER.warn("Unable to query alert recover minute, type={}, group={}, level={}; returning default value 1.", + typeName, groupName, levelName, ex); + return 1; } +} public int querySuspendMinute(String typeName, String groupName, String levelName) { + ensureInitialized(); try { Level level = queryLevel(typeName, groupName, levelName); if (level == null) { return 0; } else { - return level.getSuspendMinute(); - } - } catch (Exception ex) { - return 0; + return level.getSuspendMinute(); } + } catch (Exception ex) { + LOGGER.warn("Unable to query alert suspend minute, type={}, group={}, level={}; returning default value 0.", + typeName, groupName, levelName, ex); + return 0; } +} private boolean storeConfig() { synchronized (this) { @@ -181,8 +220,10 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored alert policy, configId={}, typeCount={}.", m_configId, m_config.getTypes().size()); } catch (Exception e) { + LOGGER.error("Unable to store alert policy, configId={}.", m_configId, e); Cat.logError(e); return false; } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/SenderConfigManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/SenderConfigManager.java index f6e60201ab..2091facbb4 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/SenderConfigManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/config/SenderConfigManager.java @@ -20,11 +20,9 @@ import java.util.List; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.sender.entity.Par; @@ -33,70 +31,102 @@ import com.dianping.cat.alarm.sender.transform.DefaultSaxParser; import com.dianping.cat.config.content.ContentFetcher; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; -@Named -public class SenderConfigManager implements Initializable { +public class SenderConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(SenderConfigManager.class); private static final String CONFIG_NAME = "senderConfig"; - @Inject - private ConfigDao m_configDao; + private ConfigRepository m_configDao; - @Inject private ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private SenderConfig m_senderConfig; + private volatile boolean m_initialized; + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + public SenderConfig getConfig() { + ensureInitialized(); return m_senderConfig; } - @Override - public void initialize() throws InitializationException { - try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); - String content = config.getContent(); - - m_senderConfig = DefaultSaxParser.parse(content); - m_configId = config.getId(); - } catch (DalNotFoundException e) { + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } try { - String content = m_fetcher.getConfigContent(CONFIG_NAME); - Config config = m_configDao.createLocal(); - - config.setName(CONFIG_NAME); - config.setContent(content); - m_configDao.insert(config); + Config config = m_configDao.findByName(CONFIG_NAME); + String content = config.getContent(); m_senderConfig = DefaultSaxParser.parse(content); m_configId = config.getId(); - } catch (Exception ex) { - Cat.logError(ex); + LOGGER.info("Loaded sender config from repository, configId={}.", m_configId); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Sender config is missing in repository, loading default content from fetcher.", e); + + try { + String content = m_fetcher.getConfigContent(CONFIG_NAME); + Config config = m_configDao.createLocal(); + + config.setName(CONFIG_NAME); + config.setContent(content); + m_configDao.insert(config); + + m_senderConfig = DefaultSaxParser.parse(content); + m_configId = config.getId(); + LOGGER.info("Initialized sender config from default content, configId={}.", m_configId); + } catch (Exception ex) { + LOGGER.error("Unable to initialize sender config from default content.", ex); + Cat.logError(ex); + } + } catch (Exception e) { + LOGGER.error("Unable to load sender config from repository.", e); + Cat.logError(e); } - } catch (Exception e) { - Cat.logError(e); + if (m_senderConfig == null) { + m_senderConfig = new SenderConfig(); + LOGGER.warn("Sender config is empty after initialization, using a new empty config."); + } + m_initialized = true; } - if (m_senderConfig == null) { - m_senderConfig = new SenderConfig(); + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); } } public boolean insert(Sender sender) { + ensureInitialized(); m_senderConfig.getSenders().put(sender.getId(), sender); return storeConfig(); } public boolean insert(String xml) { + ensureInitialized(); try { m_senderConfig = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse sender config xml for insert. xmlLength={}.", xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } @@ -131,10 +161,12 @@ public String queryParString(Sender sender) { } public Sender querySender(String id) { + ensureInitialized(); return m_senderConfig.getSenders().get(id); } public boolean remove(String id) { + ensureInitialized(); m_senderConfig.removeSender(id); return storeConfig(); @@ -149,12 +181,16 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_senderConfig.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored sender config, configId={}, senderCount={}.", m_configId, + m_senderConfig.getSenders().size()); } catch (Exception e) { + LOGGER.error("Unable to store sender config, configId={}.", m_configId, e); Cat.logError(e); return false; } } return true; } + } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/DecoratorManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/DecoratorManager.java index 95b16083b2..156cf0faeb 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/DecoratorManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/DecoratorManager.java @@ -18,24 +18,26 @@ */ package com.dianping.cat.alarm.spi.decorator; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Named; -import org.unidal.tuple.Pair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.alarm.spi.AlertEntity; import com.dianping.cat.alarm.spi.AlertType; -@Named -public class DecoratorManager extends ContainerHolder implements Initializable { +public class DecoratorManager { + private static final Logger LOGGER = LoggerFactory.getLogger(DecoratorManager.class); private Map m_decorators = new HashMap(); + private volatile boolean m_initialized; + public Pair generateTitleAndContent(AlertEntity alert) { + ensureInitialized(); AlertType alertType = alert.getType(); Decorator decorator = m_decorators.get(alertType.getName()); @@ -43,15 +45,50 @@ public Pair generateTitleAndContent(AlertEntity alert) { String title = decorator.generateTitle(alert); String content = decorator.generateContent(alert); - return new Pair(title, content); + return Pair.of(title, content); } else { + LOGGER.error("Alert decorator is not configured, alertType={}, availableDecorators={}.", alertType.getName(), + m_decorators.keySet()); throw new RuntimeException("error alert type:" + alert.getType()); } } - @Override - public void initialize() throws InitializationException { - m_decorators = lookupMap(Decorator.class); + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } + if (m_decorators.isEmpty()) { + LOGGER.warn("Alert decorator manager has no configured decorators."); + } else { + LOGGER.info("Initialized alert decorator manager from Spring injection, decoratorCount={}.", + m_decorators.size()); + } + m_initialized = true; + } + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public void setDecorators(Map decorators) { + if (decorators == null || decorators.isEmpty()) { + m_decorators = new HashMap(); + } else { + m_decorators = new HashMap(decorators); + } + LOGGER.info("Configured alert decorators from Spring, decoratorKeys={}.", m_decorators.keySet()); + } + + public Map getDecorators() { + ensureInitialized(); + return Collections.unmodifiableMap(m_decorators); } } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ProjectDecorator.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ProjectDecorator.java index 8e1ef8e187..f04e7e84d8 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ProjectDecorator.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ProjectDecorator.java @@ -18,21 +18,31 @@ */ package com.dianping.cat.alarm.spi.decorator; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.util.StringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.core.dal.Project; import com.dianping.cat.service.ProjectService; public abstract class ProjectDecorator extends Decorator { + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectDecorator.class); - @Inject protected ProjectService m_projectService; + public void setProjectService(ProjectService projectService) { + m_projectService = projectService; + } + + private ProjectService getProjectService() { + return m_projectService; + } + public String buildContactInfo(String domainName) { try { - Project project = m_projectService.findByDomain(domainName); + ProjectService projectService = getProjectService(); + Project project = projectService == null ? null : projectService.findByDomain(domainName); if (project != null) { String owners = project.getOwner(); @@ -49,6 +59,7 @@ public String buildContactInfo(String domainName) { return builder.toString(); } } catch (Exception ex) { + LOGGER.error("Unable to build project contact info, domain={}.", domainName, ex); Cat.logError("build project contact info error for domain: " + domainName, ex); } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/RuleFTLDecorator.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/RuleFTLDecorator.java index 96cb114165..5f6d0fba0b 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/RuleFTLDecorator.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/RuleFTLDecorator.java @@ -24,14 +24,15 @@ import freemarker.template.Configuration; import freemarker.template.Template; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; -public class RuleFTLDecorator implements Initializable { +public class RuleFTLDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(RuleFTLDecorator.class); - public Configuration m_configuration; + public volatile Configuration m_configuration; public String generateConfigsHtml(String templateValue) { Map dataMap = new HashMap(); @@ -39,21 +40,35 @@ public String generateConfigsHtml(String templateValue) { dataMap.put("configs", templateValue); try { - Template configsTemplate = m_configuration.getTemplate("rule_configs.ftl"); + Template configsTemplate = getConfiguration().getTemplate("rule_configs.ftl"); configsTemplate.process(dataMap, sw); } catch (Exception e) { + LOGGER.error("Unable to render alert rule config html, template=rule_configs.ftl.", e); Cat.logError(e); } return sw.toString(); } - @Override - public void initialize() throws InitializationException { - m_configuration = new Configuration(); - m_configuration.setDefaultEncoding("UTF-8"); + private Configuration getConfiguration() { + if (m_configuration == null) { + initialize(); + } + return m_configuration; + } + + public void initialize() { + if (m_configuration != null) { + return; + } + + Configuration configuration = new Configuration(); + + configuration.setDefaultEncoding("UTF-8"); try { - m_configuration.setClassForTemplateLoading(this.getClass(), "/freemaker"); + configuration.setClassForTemplateLoading(this.getClass(), "/freemaker"); + m_configuration = configuration; } catch (Exception e) { + LOGGER.error("Unable to initialize alert rule FTL decorator template loading.", e); Cat.logError(e); } } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ServerRuleFTLDecorator.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ServerRuleFTLDecorator.java index 1dce71cdcf..a833fa2ea1 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ServerRuleFTLDecorator.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/decorator/ServerRuleFTLDecorator.java @@ -24,14 +24,15 @@ import freemarker.template.Configuration; import freemarker.template.Template; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; -public class ServerRuleFTLDecorator implements Initializable { +public class ServerRuleFTLDecorator { + private static final Logger LOGGER = LoggerFactory.getLogger(ServerRuleFTLDecorator.class); - public Configuration m_configuration; + public volatile Configuration m_configuration; public String generateConfigsHtml(String templateValue) { Map dataMap = new HashMap(); @@ -39,21 +40,35 @@ public String generateConfigsHtml(String templateValue) { dataMap.put("configs", templateValue); try { - Template configsTemplate = m_configuration.getTemplate("server_rule_configs.ftl"); + Template configsTemplate = getConfiguration().getTemplate("server_rule_configs.ftl"); configsTemplate.process(dataMap, sw); } catch (Exception e) { + LOGGER.error("Unable to render server alert rule config html, template=server_rule_configs.ftl.", e); Cat.logError(e); } return sw.toString(); } - @Override - public void initialize() throws InitializationException { - m_configuration = new Configuration(); - m_configuration.setDefaultEncoding("UTF-8"); + private Configuration getConfiguration() { + if (m_configuration == null) { + initialize(); + } + return m_configuration; + } + + public void initialize() { + if (m_configuration != null) { + return; + } + + Configuration configuration = new Configuration(); + + configuration.setDefaultEncoding("UTF-8"); try { - m_configuration.setClassForTemplateLoading(this.getClass(), "/freemaker"); + configuration.setClassForTemplateLoading(this.getClass(), "/freemaker"); + m_configuration = configuration; } catch (Exception e) { + LOGGER.error("Unable to initialize server alert rule FTL decorator template loading.", e); Cat.logError(e); } } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ContactorManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ContactorManager.java index 8f5257c762..fa2f93277c 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ContactorManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ContactorManager.java @@ -18,29 +18,56 @@ */ package com.dianping.cat.alarm.spi.receiver; -import com.dianping.cat.alarm.spi.AlertChannel; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Named; - +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -@Named -public class ContactorManager extends ContainerHolder implements Initializable { +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.dianping.cat.alarm.spi.AlertChannel; + +public class ContactorManager { + private static final Logger LOGGER = LoggerFactory.getLogger(ContactorManager.class); private Map m_contactors = new HashMap(); - @Override - public void initialize() throws InitializationException { - m_contactors = lookupMap(Contactor.class); + private volatile boolean m_initialized; + + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } + if (m_contactors.isEmpty()) { + LOGGER.warn("Alert contactor manager has no configured contactors."); + } else { + LOGGER.info("Initialized alert contactor manager from Spring injection, contactorCount={}.", + m_contactors.size()); + } + m_initialized = true; + } + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } } public List queryReceivers(String group, AlertChannel channel, String type) { + ensureInitialized(); Contactor contactor = m_contactors.get(type); + if (contactor == null) { + LOGGER.error("Alert contactor is not configured, type={}, channel={}, group={}, availableContactors={}.", type, + channel, group, m_contactors.keySet()); + throw new IllegalStateException("Alert contactor is not configured for type: " + type); + } if (AlertChannel.MAIL == channel) { return contactor.queryEmailContactors(group); } else if (AlertChannel.SMS == channel) { @@ -50,8 +77,23 @@ public List queryReceivers(String group, AlertChannel channel, String ty } else if (AlertChannel.DX == channel) { return contactor.queryDXContactors(group); } else { + LOGGER.error("Unsupported alert receiver channel, type={}, channel={}, group={}.", type, channel, group); throw new RuntimeException("unsupported channel"); } } + public void setContactors(Map contactors) { + if (contactors == null || contactors.isEmpty()) { + m_contactors = new HashMap(); + } else { + m_contactors = new HashMap(contactors); + } + LOGGER.info("Configured alert contactors from Spring, contactorKeys={}.", m_contactors.keySet()); + } + + public Map getContactors() { + ensureInitialized(); + return Collections.unmodifiableMap(m_contactors); + } + } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/DefaultContactor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/DefaultContactor.java index 27804b7cde..9c18299edc 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/DefaultContactor.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/DefaultContactor.java @@ -21,8 +21,6 @@ import java.util.ArrayList; import java.util.List; -import org.unidal.helper.Splitters; - import com.dianping.cat.alarm.receiver.entity.Receiver; public abstract class DefaultContactor { @@ -67,7 +65,13 @@ protected List split(String str) { List result = new ArrayList(); if (str != null) { - result.addAll(Splitters.by(",").noEmptyItem().trim().split(str)); + for (String item : str.split(",")) { + String value = item.trim(); + + if (value.length() > 0) { + result.add(value); + } + } } return result; diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ProjectContactor.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ProjectContactor.java index e361199715..34b7e4cccd 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ProjectContactor.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/receiver/ProjectContactor.java @@ -21,8 +21,7 @@ import java.util.ArrayList; import java.util.List; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.util.StringUtils; +import org.apache.commons.lang.StringUtils; import com.dianping.cat.alarm.receiver.entity.Receiver; import com.dianping.cat.alarm.spi.config.AlertConfigManager; @@ -31,16 +30,23 @@ public abstract class ProjectContactor extends DefaultContactor implements Contactor { - @Inject protected ProjectService m_projectService; - @Inject protected AlertConfigManager m_configManager; + private AlertConfigManager getConfigManager() { + return m_configManager; + } + + private ProjectService getProjectService() { + return m_projectService; + } + @Override public List queryEmailContactors(String id) { List mailReceivers = new ArrayList(); - Receiver receiver = m_configManager.queryReceiverById(getId()); + AlertConfigManager configManager = getConfigManager(); + Receiver receiver = configManager == null ? null : configManager.queryReceiverById(getId()); if (receiver != null && !receiver.isEnable()) { return mailReceivers; @@ -48,7 +54,8 @@ public List queryEmailContactors(String id) { mailReceivers.addAll(buildDefaultMailReceivers(receiver)); if (StringUtils.isNotEmpty(id)) { - Project project = m_projectService.findByDomain(id); + ProjectService projectService = getProjectService(); + Project project = projectService == null ? null : projectService.findByDomain(id); if (project != null) { mailReceivers.addAll(split(project.getEmail())); @@ -61,7 +68,8 @@ public List queryEmailContactors(String id) { @Override public List querySmsContactors(String id) { List smsReceivers = new ArrayList(); - Receiver receiver = m_configManager.queryReceiverById(getId()); + AlertConfigManager configManager = getConfigManager(); + Receiver receiver = configManager == null ? null : configManager.queryReceiverById(getId()); if (receiver != null && !receiver.isEnable()) { return smsReceivers; @@ -69,7 +77,8 @@ public List querySmsContactors(String id) { smsReceivers.addAll(buildDefaultSMSReceivers(receiver)); if (StringUtils.isNotEmpty(id)) { - Project project = m_projectService.findByDomain(id); + ProjectService projectService = getProjectService(); + Project project = projectService == null ? null : projectService.findByDomain(id); if (project != null) { smsReceivers.addAll(split(project.getPhone())); @@ -82,7 +91,8 @@ public List querySmsContactors(String id) { @Override public List queryWeiXinContactors(String id) { List weixinReceivers = new ArrayList(); - Receiver receiver = m_configManager.queryReceiverById(getId()); + AlertConfigManager configManager = getConfigManager(); + Receiver receiver = configManager == null ? null : configManager.queryReceiverById(getId()); if (receiver != null && !receiver.isEnable()) { return weixinReceivers; @@ -90,7 +100,8 @@ public List queryWeiXinContactors(String id) { weixinReceivers.addAll(buildDefaultWeixinReceivers(receiver)); if (StringUtils.isNotEmpty(id)) { - Project project = m_projectService.findByDomain(id); + ProjectService projectService = getProjectService(); + Project project = projectService == null ? null : projectService.findByDomain(id); if (project != null) { weixinReceivers.addAll(split(project.getEmail())); @@ -103,7 +114,8 @@ public List queryWeiXinContactors(String id) { @Override public List queryDXContactors(String id) { List receivers = new ArrayList(); - Receiver receiver = m_configManager.queryReceiverById(getId()); + AlertConfigManager configManager = getConfigManager(); + Receiver receiver = configManager == null ? null : configManager.queryReceiverById(getId()); if (receiver != null && !receiver.isEnable()) { return receivers; @@ -111,7 +123,8 @@ public List queryDXContactors(String id) { receivers.addAll(buildDefaultDXReceivers(receiver)); if (StringUtils.isNotEmpty(id)) { - Project project = m_projectService.findByDomain(id); + ProjectService projectService = getProjectService(); + Project project = projectService == null ? null : projectService.findByDomain(id); if (project != null) { receivers.addAll(split(project.getEmail())); @@ -121,4 +134,12 @@ public List queryDXContactors(String id) { } } + public void setConfigManager(AlertConfigManager configManager) { + m_configManager = configManager; + } + + public void setProjectService(ProjectService projectService) { + m_projectService = projectService; + } + } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/DefaultDataChecker.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/DefaultDataChecker.java index abe27c90ea..5619f25c4d 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/DefaultDataChecker.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/DefaultDataChecker.java @@ -21,14 +21,15 @@ import com.dianping.cat.Cat; import com.dianping.cat.alarm.rule.entity.Condition; import com.dianping.cat.alarm.rule.entity.SubCondition; -import org.unidal.lookup.annotation.Named; -import org.unidal.tuple.Pair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; -@Named(type = DataChecker.class) public class DefaultDataChecker implements DataChecker { + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultDataChecker.class); private double[] buildLastMinutesDoubleArray(double[] doubleList, int remainCount) { if (doubleList.length <= remainCount) { @@ -92,16 +93,18 @@ private Pair checkDataByCondition(double[] value, double[] base Pair subResult = rule.executeRule(value, baseline, subCondition.getText()); if (!subResult.getKey()) { - return new Pair(false, ""); + return Pair.of(false, ""); } builder.append(subResult.getValue()).append("
"); } catch (Exception ex) { + LOGGER.error("Unable to check alert rule condition, condition={}, subCondition={}.", condition, + subCondition, ex); Cat.logError(condition.toString(), ex); - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, builder.toString()); + return Pair.of(true, builder.toString()); } public List checkDataForApp(double[] value, List conditions) { diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/RuleType.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/RuleType.java index 669f07efd7..5636616d05 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/RuleType.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/rule/RuleType.java @@ -19,7 +19,9 @@ package com.dianping.cat.alarm.spi.rule; import com.dianping.cat.Cat; -import org.unidal.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.commons.lang3.tuple.Pair; import javax.tools.JavaCompiler; import javax.tools.ToolProvider; @@ -72,11 +74,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (baselines[i] <= 0 || values[i] / baselines[i] > (1 - ruleValue / 100)) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -120,11 +122,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (baselines[i] - values[i] < ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -167,11 +169,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (baselines[i] <= 0 || values[i] / baselines[i] < (1 + ruleValue / 100)) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -214,11 +216,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (values[i] - baselines[i] < ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -247,11 +249,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (values[i] < ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -280,11 +282,11 @@ public Pair executeRule(double[] values, double[] baselines, St for (int i = 0; i < length; i++) { if (values[i] > ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -326,18 +328,18 @@ public Pair executeRule(double[] values, double[] baselines, St int length = values.length; if (length <= 1) { - return new Pair(false, ""); + return Pair.of(false, ""); } double baseVal = values[length - 1]; for (int i = 0; i <= length - 2; i++) { if (baseVal / values[i] - 1 < ruleValue / 100) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -379,18 +381,18 @@ public Pair executeRule(double[] values, double[] baselines, St int length = values.length; if (length <= 1) { - return new Pair(false, ""); + return Pair.of(false, ""); } double baseVal = values[length - 1]; for (int i = 0; i <= length - 2; i++) { if (1 - baseVal / values[i] < ruleValue / 100) { - return new Pair(false, ""); + return Pair.of(false, ""); } } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -419,10 +421,10 @@ public Pair executeRule(double[] values, double[] baselines, St double totalVal = calSum(values); if (totalVal < ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -451,10 +453,10 @@ public Pair executeRule(double[] values, double[] baselines, St double totalVal = calSum(values); if (totalVal > ruleValue) { - return new Pair(false, ""); + return Pair.of(false, ""); } - return new Pair(true, buildRuleMessage(values, baselines, ruleValue)); + return Pair.of(true, buildRuleMessage(values, baselines, ruleValue)); } @Override @@ -491,8 +493,10 @@ public Pair executeRule(double[] values, double[] baselines, St m_rules.put(rawValue, instance); } catch (Exception e) { + LOGGER.error("Unable to generate user defined alert rule, rawValueLength={}.", + rawValue == null ? 0 : rawValue.length(), e); Cat.logError("generate user defined rule error: " + rawValue, e); - return new Pair(false, ""); + return Pair.of(false, ""); } } return instance.checkData(values, baselines); @@ -515,7 +519,7 @@ private Pair generateClassFile(String rawValue) throws IOException { } finally { output.close(); } - return new Pair(userDefinedFolder, userDefinedClassFile); + return Pair.of(userDefinedFolder, userDefinedClassFile); } @Override @@ -524,6 +528,8 @@ public String getId() { } }; + private static final Logger LOGGER = LoggerFactory.getLogger(RuleType.class); + protected static final long MbS = 60 * 1024 * 1024; protected static final long GbS = MbS * 1024; diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/AbstractSender.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/AbstractSender.java index 665c2540fc..306ce66f12 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/AbstractSender.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/AbstractSender.java @@ -23,25 +23,20 @@ import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; +import java.nio.charset.StandardCharsets; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Files; -import org.unidal.lookup.annotation.Inject; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.spi.config.SenderConfigManager; -public abstract class AbstractSender implements Sender, LogEnabled { +public abstract class AbstractSender implements Sender { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AbstractSender.class); - @Inject protected SenderConfigManager m_senderConfigManager; - protected Logger m_logger; - - @Override - public void enableLogging(Logger logger) { - m_logger = logger; + public void setSenderConfigManager(SenderConfigManager senderConfigManager) { + m_senderConfigManager = senderConfigManager; } private boolean httpGetSend(String successCode, String urlPrefix, String urlPars) { @@ -58,17 +53,18 @@ private boolean httpGetSend(String successCode, String urlPrefix, String urlPars conn.setReadTimeout(3000); in = conn.getInputStream(); - StringBuilder sb = new StringBuilder(); - sb.append(Files.forIO().readFrom(in, "utf-8")).append(""); + String response = new String(in.readAllBytes(), StandardCharsets.UTF_8); - if (sb.toString().contains(successCode)) { + if (response.contains(successCode)) { sendSuccess = true; return true; } else { + LOGGER.warn("Alert HTTP GET returned unexpected response, urlPrefix={}, successCode={}, response={}.", + urlPrefix, successCode, response); return false; } } catch (Exception e) { - m_logger.error(e.getMessage(), e); + LOGGER.error("Unable to send alert by HTTP GET, urlPrefix={}, urlPars={}.", urlPrefix, urlPars, e); return false; } finally { try { @@ -76,6 +72,7 @@ private boolean httpGetSend(String successCode, String urlPrefix, String urlPars in.close(); } } catch (IOException e) { + LOGGER.warn("Unable to close alert HTTP GET response stream, urlPrefix={}.", urlPrefix, e); } if (!sendSuccess) { recordSendLog(urlPrefix, urlPars); @@ -105,17 +102,18 @@ private boolean httpPostSend(String successCode, String urlPrefix, String conten writer.flush(); in = conn.getInputStream(); - StringBuilder sb = new StringBuilder(); - - sb.append(Files.forIO().readFrom(in, "utf-8")).append(""); - if (sb.toString().contains(successCode)) { + String response = new String(in.readAllBytes(), StandardCharsets.UTF_8); + if (response.contains(successCode)) { sendSuccess = true; return true; } else { + LOGGER.warn("Alert HTTP POST returned unexpected response, urlPrefix={}, successCode={}, response={}.", + urlPrefix, successCode, response); return false; } } catch (Exception e) { - m_logger.error(e.getMessage(), e); + LOGGER.error("Unable to send alert by HTTP POST, urlPrefix={}, contentLength={}.", urlPrefix, + content == null ? 0 : content.length(), e); return false; } finally { try { @@ -126,6 +124,7 @@ private boolean httpPostSend(String successCode, String urlPrefix, String conten writer.close(); } } catch (IOException e) { + LOGGER.warn("Unable to close alert HTTP POST resources, urlPrefix={}.", urlPrefix, e); } if (!sendSuccess) { recordSendLog(urlPrefix, content); @@ -139,6 +138,7 @@ public boolean httpSend(String successCode, String type, String urlPrefix, Strin } else if ("post".equalsIgnoreCase(type)) { return httpPostSend(successCode, urlPrefix, urlPars); } else { + LOGGER.error("Illegal alert sender request type, type={}, urlPrefix={}.", type, urlPrefix); Cat.logError(new RuntimeException("Illegal request type: " + type)); return false; } @@ -151,6 +151,7 @@ public com.dianping.cat.alarm.sender.entity.Sender querySender() { } private void recordSendLog(String urlPrefix, String paras) { + LOGGER.error("Alert send failed, urlPrefix={}, paras={}.", urlPrefix, paras, new AlertSendException()); Cat.logError(urlPrefix + "---" + paras, new AlertSendException()); } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/MailSender.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/MailSender.java index cf4145c158..741ed1a35c 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/MailSender.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/MailSender.java @@ -23,11 +23,15 @@ import java.util.Date; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.dianping.cat.Cat; import com.dianping.cat.alarm.sender.entity.Sender; import com.dianping.cat.alarm.spi.AlertChannel; public class MailSender extends AbstractSender { + private static final Logger LOGGER = LoggerFactory.getLogger(MailSender.class); public static final String ID = AlertChannel.MAIL.getName(); @@ -70,6 +74,8 @@ private boolean sendEmail(SendMessageEntity message, String receiver, Sender sen .replace("${time}", URLEncoder.encode(time, "utf-8")); } catch (Exception e) { + LOGGER.error("Unable to encode mail alert request parameters, receiver={}, title={}.", receiver, + message.getTitle(), e); Cat.logError(e); } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SenderManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SenderManager.java index 624773803c..fb1eef59f3 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SenderManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SenderManager.java @@ -18,49 +18,95 @@ */ package com.dianping.cat.alarm.spi.sender; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.alarm.spi.AlertChannel; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.Event; -@Named -public class SenderManager extends ContainerHolder implements Initializable { +public class SenderManager { + private static final Logger LOGGER = LoggerFactory.getLogger(SenderManager.class); - @Inject private ServerConfigManager m_configManager; private Map m_senders = new HashMap(); - @Override - public void initialize() throws InitializationException { - m_senders = lookupMap(Sender.class); + private volatile boolean m_initialized; + + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } + if (m_senders.isEmpty()) { + LOGGER.warn("Alert sender manager has no configured senders."); + } else { + LOGGER.info("Initialized alert sender manager from Spring injection, senderCount={}.", m_senders.size()); + } + m_initialized = true; + } + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public void setSenders(Map senders) { + if (senders == null || senders.isEmpty()) { + m_senders = new HashMap(); + } else { + m_senders = new HashMap(senders); + } + LOGGER.info("Configured alert senders from Spring, senderKeys={}.", m_senders.keySet()); + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + + public Map getSenders() { + ensureInitialized(); + return Collections.unmodifiableMap(m_senders); } public boolean sendAlert(AlertChannel channel, SendMessageEntity message) { + ensureInitialized(); String channelName = channel.getName(); try { boolean result = false; String str = "nosend"; - if (m_configManager.isSendMachine()) { + if (m_configManager != null && m_configManager.isSendMachine()) { Sender sender = m_senders.get(channelName); + if (sender == null) { + LOGGER.warn("Alert sender is not configured, channel={}, messageType={}.", channelName, + message.getType()); + Cat.logEvent("Channel:" + channel, message.getType() + ":nosender", Event.SUCCESS, null); + return false; + } result = sender.send(message); str = String.valueOf(result); + } else { + LOGGER.info("Current machine is not configured as send machine, skip alert sending, channel={}, type={}.", + channelName, message.getType()); } Cat.logEvent("Channel:" + channel, message.getType() + ":" + str, Event.SUCCESS, null); return result; } catch (Exception e) { + LOGGER.error("Unable to send alert, channel={}, message={}.", channel, message, e); Cat.logError("Channel [" + channel + "] " + message.toString(), e); return false; } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SmsSender.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SmsSender.java index 42a0b3cfda..85e59d08b6 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SmsSender.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/SmsSender.java @@ -21,11 +21,15 @@ import java.net.URLEncoder; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.dianping.cat.Cat; import com.dianping.cat.alarm.sender.entity.Sender; import com.dianping.cat.alarm.spi.AlertChannel; public class SmsSender extends AbstractSender { + private static final Logger LOGGER = LoggerFactory.getLogger(SmsSender.class); public static final String ID = AlertChannel.SMS.getName(); @@ -65,6 +69,8 @@ private boolean sendSms(SendMessageEntity message, String receiver, Sender sende urlPars = urlPars.replace("${receiver}", URLEncoder.encode(receiver, "utf-8")) .replace("${content}", URLEncoder.encode(content, "utf-8")); } catch (Exception e) { + LOGGER.error("Unable to encode SMS alert request parameters, receiver={}, title={}.", receiver, + message.getTitle(), e); Cat.logError(e); } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/WeixinSender.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/WeixinSender.java index 3756aee1f6..9322996e6e 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/WeixinSender.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/sender/WeixinSender.java @@ -21,11 +21,15 @@ import java.net.URLEncoder; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.dianping.cat.Cat; import com.dianping.cat.alarm.sender.entity.Sender; import com.dianping.cat.alarm.spi.AlertChannel; public class WeixinSender extends AbstractSender { + private static final Logger LOGGER = LoggerFactory.getLogger(WeixinSender.class); public static final String ID = AlertChannel.WEIXIN.getName(); @@ -69,6 +73,8 @@ private boolean sendWeixin(SendMessageEntity message, String receiver, Sender se .replace("${content}", URLEncoder.encode(content, "utf-8")) .replace("${type}", URLEncoder.encode(message.getType(), "utf-8")); } catch (Exception e) { + LOGGER.error("Unable to encode Weixin alert request parameters, domain={}, receiver={}, title={}.", domain, + receiver, message.getTitle(), e); Cat.logError(e); } diff --git a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/spliter/SpliterManager.java b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/spliter/SpliterManager.java index a78cc9ac34..7bbfb2fc8d 100644 --- a/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/spliter/SpliterManager.java +++ b/cat-alarm/src/main/java/com/dianping/cat/alarm/spi/spliter/SpliterManager.java @@ -18,31 +18,71 @@ */ package com.dianping.cat.alarm.spi.spliter; +import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.alarm.spi.AlertChannel; -@Named -public class SpliterManager extends ContainerHolder implements Initializable { +public class SpliterManager { + private static final Logger LOGGER = LoggerFactory.getLogger(SpliterManager.class); private Map m_spliters = new HashMap(); - @Override - public void initialize() throws InitializationException { - m_spliters = lookupMap(Spliter.class); + private volatile boolean m_initialized; + + public void initialize() { + if (m_initialized) { + return; + } + synchronized (this) { + if (m_initialized) { + return; + } + if (m_spliters.isEmpty()) { + LOGGER.warn("Alert splitter manager has no configured splitters."); + } else { + LOGGER.info("Initialized alert splitter manager from Spring injection, splitterCount={}.", + m_spliters.size()); + } + m_initialized = true; + } + } + + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } } public String process(String content, AlertChannel channel) { + ensureInitialized(); String channelName = channel.getName(); Spliter splitter = m_spliters.get(channelName); + if (splitter == null) { + LOGGER.error("Alert splitter is not configured, channel={}, availableSplitters={}.", channelName, + m_spliters.keySet()); + throw new IllegalStateException("Alert splitter is not configured for channel: " + channelName); + } return splitter.process(content); } + public void setSpliters(Map spliters) { + if (spliters == null || spliters.isEmpty()) { + m_spliters = new HashMap(); + } else { + m_spliters = new HashMap(spliters); + } + LOGGER.info("Configured alert splitters from Spring, splitterKeys={}.", m_spliters.keySet()); + } + + public Map getSpliters() { + ensureInitialized(); + return Collections.unmodifiableMap(m_spliters); + } + } diff --git a/cat-alarm/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java b/cat-alarm/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java deleted file mode 100644 index 0902ecb56c..0000000000 --- a/cat-alarm/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.build; - -import org.unidal.dal.jdbc.configuration.AbstractJdbcResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import java.util.ArrayList; -import java.util.List; - -final class CatDatabaseConfigurator extends AbstractJdbcResourceConfigurator { - @Override - public List defineComponents() { - List all = new ArrayList(); - - // all.add(defineJdbcDataSourceComponent("cat", "com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/cat", "root", "***", "")); - - defineSimpleTableProviderComponents(all, "cat", com.dianping.cat.alarm._INDEX.getEntityClasses()); - defineDaoComponents(all, com.dianping.cat.alarm._INDEX.getDaoClasses()); - - return all; - } -} diff --git a/cat-alarm/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java b/cat-alarm/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java deleted file mode 100644 index aa68a0098c..0000000000 --- a/cat-alarm/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.build; - -import com.dianping.cat.alarm.service.AlertService; -import com.dianping.cat.alarm.spi.AlertManager; -import com.dianping.cat.alarm.spi.config.AlertConfigManager; -import com.dianping.cat.alarm.spi.config.AlertPolicyManager; -import com.dianping.cat.alarm.spi.config.SenderConfigManager; -import com.dianping.cat.alarm.spi.decorator.DecoratorManager; -import com.dianping.cat.alarm.spi.receiver.ContactorManager; -import com.dianping.cat.alarm.spi.rule.DefaultDataChecker; -import com.dianping.cat.alarm.spi.sender.*; -import com.dianping.cat.alarm.spi.spliter.*; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import java.util.ArrayList; -import java.util.List; - -public class ComponentsConfigurator extends AbstractResourceConfigurator { - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new ComponentsConfigurator()); - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - - all.addAll(new CatDatabaseConfigurator().defineComponents()); - - all.add(A(SenderConfigManager.class)); - - all.add(A(DefaultDataChecker.class)); - all.add(A(DecoratorManager.class)); - all.add(A(ContactorManager.class)); - - all.add(A(AlertPolicyManager.class)); - - all.add(C(Spliter.class, MailSpliter.ID, MailSpliter.class)); - - all.add(C(Spliter.class, SmsSpliter.ID, SmsSpliter.class)); - - all.add(C(Spliter.class, WeixinSpliter.ID, WeixinSpliter.class)); - - all.add(C(Spliter.class, DXSpliter.ID, DXSpliter.class)); - - all.add(A(SpliterManager.class)); - - all.add(C(Sender.class, MailSender.ID, MailSender.class).req(SenderConfigManager.class)); - - all.add(C(Sender.class, SmsSender.ID, SmsSender.class).req(SenderConfigManager.class)); - - all.add(C(Sender.class, WeixinSender.ID, WeixinSender.class).req(SenderConfigManager.class)); - - all.add(A(SenderManager.class)); - - all.add(A(AlertManager.class)); - - all.add(A(AlertService.class)); - - all.add(A(AlertConfigManager.class)); - - return all; - } -} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/AlertMapper.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/AlertMapper.java new file mode 100644 index 0000000000..438f42255c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/AlertMapper.java @@ -0,0 +1,27 @@ +package com.dianping.cat.mybatis.alert.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.alert.dao.data.AlertDO; + +public interface AlertMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + AlertDO findByPrimaryKey(@Param("id") Long id); + + int insert(AlertDO record); + + List queryAll(); + + int updateByPrimaryKey(AlertDO record); + + List queryAlertsByTimeDomain(@Param("record") AlertDO record); + + List queryAlertsByTimeDomainCategories(@Param("record") AlertDO record); + + List queryAlertsByTimeCategoryDomain(@Param("record") AlertDO record); + + List queryAlertsByTimeCategory(@Param("record") AlertDO record); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/data/AlertDO.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/data/AlertDO.java new file mode 100644 index 0000000000..36d77baaca --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/alert/dao/data/AlertDO.java @@ -0,0 +1,34 @@ +package com.dianping.cat.mybatis.alert.dao.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class AlertDO { + private Long id; + + private String domain; + + private Date alertTime; + + private String category; + + private String type; + + private String content; + + private String metric; + + private Date createTime; + + private Date updateTime; + + private Long keyId; + + private Date startTime; + + private Date endTime; + + private String[] categories; +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/alert/AlertRepository.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/alert/AlertRepository.java new file mode 100644 index 0000000000..685016cf80 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/alert/AlertRepository.java @@ -0,0 +1,198 @@ +package com.dianping.cat.mybatis.repository.alert; + +import com.dianping.cat.alarm.Alert; +import com.dianping.cat.mybatis.alert.dao.AlertMapper; +import com.dianping.cat.mybatis.alert.dao.data.AlertDO; +import com.dianping.cat.mybatis.SpringBackedRepositorySupport; +import java.util.List; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.dao.EmptyResultDataAccessException; + +public class AlertRepository extends SpringBackedRepositorySupport { + private static final Logger LOGGER = LoggerFactory.getLogger(AlertRepository.class); + + private static final String MAPPER_RESOURCE = "mybatis/mapper/AlertMapper.xml"; + + public AlertRepository() { + super(AlertMapper.class, MAPPER_RESOURCE, "AlertRepository is using Spring managed AlertMapper."); + } + + public Alert createLocal() { + return new Alert(); + } + + public int deleteByPK(Alert proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).deleteByPrimaryKey(proto.getKeyId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for Alert.", e); + } + } + + public List queryAlertsByTimeDomain(java.util.Date startTime, java.util.Date endTime, String domain) { + AlertMapper mapper = springMapper(LOGGER); + AlertDO record = new AlertDO(); + + record.setStartTime(startTime); + record.setEndTime(endTime); + record.setDomain(domain); + try { + return mapper.queryAlertsByTimeDomain(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing queryAlertsByTimeDomain for Alert.", e); + } + } + + public List queryAlertsByTimeDomainCategories(java.util.Date startTime, java.util.Date endTime, String domain, String[] categories) { + AlertMapper mapper = springMapper(LOGGER); + AlertDO record = new AlertDO(); + + record.setStartTime(startTime); + record.setEndTime(endTime); + record.setDomain(domain); + record.setCategories(categories); + try { + return mapper.queryAlertsByTimeDomainCategories(record).stream().map(this::toModel) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing queryAlertsByTimeDomainCategories for Alert.", e); + } + } + + public List queryAlertsByTimeCategoryDomain(java.util.Date startTime, java.util.Date endTime, String category, String domain) { + AlertMapper mapper = springMapper(LOGGER); + AlertDO record = new AlertDO(); + + record.setStartTime(startTime); + record.setEndTime(endTime); + record.setCategory(category); + record.setDomain(domain); + try { + return mapper.queryAlertsByTimeCategoryDomain(record).stream().map(this::toModel) + .collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing queryAlertsByTimeCategoryDomain for Alert.", e); + } + } + + public List queryAlertsByTimeCategory(java.util.Date startTime, java.util.Date endTime, String category) { + AlertMapper mapper = springMapper(LOGGER); + AlertDO record = new AlertDO(); + + record.setStartTime(startTime); + record.setEndTime(endTime); + record.setCategory(category); + try { + return mapper.queryAlertsByTimeCategory(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing queryAlertsByTimeCategory for Alert.", e); + } + } + + public Alert findByPK(int keyId) { + return findByPK((long) keyId); + } + + public Alert findByPK(long keyId) { + AlertMapper mapper = springMapper(LOGGER); + + try { + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for Alert.", e); + } + } + + public int insert(Alert proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + AlertDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper(LOGGER).insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for Alert.", e); + } + } + + public int updateByPK(Alert proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for Alert.", e); + } + } + + private Alert requireFound(AlertDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No Alert found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private Alert toModel(AlertDO record) { + Alert model = new Alert(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getAlertTime() != null) { + model.setAlertTime(record.getAlertTime()); + } + if (record.getCategory() != null) { + model.setCategory(record.getCategory()); + } + if (record.getType() != null) { + model.setType(record.getType()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getMetric() != null) { + model.setMetric(record.getMetric()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + model.afterLoad(); + return model; + } + + private AlertDO toRecord(Alert model) { + AlertDO record = new AlertDO(); + + record.setId(model.getId()); + record.setDomain(model.getDomain()); + record.setAlertTime(model.getAlertTime()); + record.setCategory(model.getCategory()); + record.setType(model.getType()); + record.setContent(model.getContent()); + record.setMetric(model.getMetric()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + record.setStartTime(model.getStartTime()); + record.setEndTime(model.getEndTime()); + record.setCategories(model.getCategories()); + return record; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/server/alarm/rule/ServerAlarmRuleRepository.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/server/alarm/rule/ServerAlarmRuleRepository.java new file mode 100644 index 0000000000..afec1c9533 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/server/alarm/rule/ServerAlarmRuleRepository.java @@ -0,0 +1,151 @@ +package com.dianping.cat.mybatis.repository.server.alarm.rule; + +import com.dianping.cat.alarm.ServerAlarmRule; +import com.dianping.cat.mybatis.server.alarm.rule.dao.ServerAlarmRuleMapper; +import com.dianping.cat.mybatis.server.alarm.rule.dao.data.ServerAlarmRuleDO; +import com.dianping.cat.mybatis.SpringBackedRepositorySupport; +import java.util.List; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.dao.EmptyResultDataAccessException; + +public class ServerAlarmRuleRepository extends SpringBackedRepositorySupport { + private static final Logger LOGGER = LoggerFactory.getLogger(ServerAlarmRuleRepository.class); + + private static final String MAPPER_RESOURCE = "mybatis/mapper/ServerAlarmRuleMapper.xml"; + + public ServerAlarmRuleRepository() { + super(ServerAlarmRuleMapper.class, MAPPER_RESOURCE, + "ServerAlarmRuleRepository is using Spring managed ServerAlarmRuleMapper."); + } + + public ServerAlarmRule createLocal() { + return new ServerAlarmRule(); + } + + public int deleteByPK(ServerAlarmRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).deleteByPrimaryKey(proto.getKeyId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for ServerAlarmRule.", e); + } + } + + public List findAll() { + ServerAlarmRuleMapper mapper = springMapper(LOGGER); + ServerAlarmRuleDO record = new ServerAlarmRuleDO(); + + try { + return mapper.findAll(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing findAll for ServerAlarmRule.", e); + } + } + + public ServerAlarmRule findByPK(int keyId) { + return findByPK((long) keyId); + } + + public ServerAlarmRule findByPK(long keyId) { + ServerAlarmRuleMapper mapper = springMapper(LOGGER); + + try { + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for ServerAlarmRule.", e); + } + } + + public int insert(ServerAlarmRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + ServerAlarmRuleDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper(LOGGER).insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for ServerAlarmRule.", e); + } + } + + public int updateByPK(ServerAlarmRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for ServerAlarmRule.", e); + } + } + + private ServerAlarmRule requireFound(ServerAlarmRuleDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No ServerAlarmRule found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private ServerAlarmRule toModel(ServerAlarmRuleDO record) { + ServerAlarmRule model = new ServerAlarmRule(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getCategory() != null) { + model.setCategory(record.getCategory()); + } + if (record.getEndPoint() != null) { + model.setEndPoint(record.getEndPoint()); + } + if (record.getMeasurement() != null) { + model.setMeasurement(record.getMeasurement()); + } + if (record.getTags() != null) { + model.setTags(record.getTags()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getType() != null) { + model.setType(record.getType()); + } + if (record.getCreator() != null) { + model.setCreator(record.getCreator()); + } + if (record.getCreationDate() != null) { + model.setCreationDate(record.getCreationDate()); + } + if (record.getUpdatetime() != null) { + model.setUpdatetime(record.getUpdatetime()); + } + model.afterLoad(); + return model; + } + + private ServerAlarmRuleDO toRecord(ServerAlarmRule model) { + ServerAlarmRuleDO record = new ServerAlarmRuleDO(); + + record.setId(model.getId()); + record.setCategory(model.getCategory()); + record.setEndPoint(model.getEndPoint()); + record.setMeasurement(model.getMeasurement()); + record.setTags(model.getTags()); + record.setContent(model.getContent()); + record.setType(model.getType()); + record.setCreator(model.getCreator()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + return record; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/user/define/rule/UserDefineRuleRepository.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/user/define/rule/UserDefineRuleRepository.java new file mode 100644 index 0000000000..9798bedee0 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/repository/user/define/rule/UserDefineRuleRepository.java @@ -0,0 +1,132 @@ +package com.dianping.cat.mybatis.repository.user.define.rule; + +import com.dianping.cat.alarm.UserDefineRule; +import com.dianping.cat.mybatis.user.define.rule.dao.UserDefineRuleMapper; +import com.dianping.cat.mybatis.user.define.rule.dao.data.UserDefineRuleDO; +import com.dianping.cat.mybatis.SpringBackedRepositorySupport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.transaction.support.TransactionTemplate; +import org.springframework.dao.EmptyResultDataAccessException; + +public class UserDefineRuleRepository extends SpringBackedRepositorySupport { + private static final Logger LOGGER = LoggerFactory.getLogger(UserDefineRuleRepository.class); + + private static final String MAPPER_RESOURCE = "mybatis/mapper/UserDefineRuleMapper.xml"; + + public UserDefineRuleRepository() { + super(UserDefineRuleMapper.class, MAPPER_RESOURCE, + "UserDefineRuleRepository is using Spring managed UserDefineRuleMapper."); + } + + public UserDefineRule createLocal() { + return new UserDefineRule(); + } + + public int deleteByPK(UserDefineRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).deleteByPrimaryKey(proto.getKeyId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for UserDefineRule.", e); + } + } + + public UserDefineRule findByPK(int keyId) { + return findByPK((long) keyId); + } + + public UserDefineRule findByPK(long keyId) { + UserDefineRuleMapper mapper = springMapper(LOGGER); + + try { + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for UserDefineRule.", e); + } + } + + public UserDefineRule findMaxId() { + UserDefineRuleMapper mapper = springMapper(LOGGER); + UserDefineRuleDO record = new UserDefineRuleDO(); + + try { + UserDefineRuleDO result = mapper.findMaxId(record).stream().findFirst().orElse(null); + + return requireFound(result, "findMaxId", record.toString()); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findMaxId for UserDefineRule.", e); + } + } + + public int insert(UserDefineRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + UserDefineRuleDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper(LOGGER).insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for UserDefineRule.", e); + } + } + + public int updateByPK(UserDefineRule proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper(LOGGER).updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for UserDefineRule.", e); + } + } + + private UserDefineRule requireFound(UserDefineRuleDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No UserDefineRule found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private UserDefineRule toModel(UserDefineRuleDO record) { + UserDefineRule model = new UserDefineRule(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getCreationDate() != null) { + model.setCreationDate(record.getCreationDate()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getMaxId() != null) { + model.setMaxId(record.getMaxId()); + } + model.afterLoad(); + return model; + } + + private UserDefineRuleDO toRecord(UserDefineRule model) { + UserDefineRuleDO record = new UserDefineRuleDO(); + + record.setId(model.getId()); + record.setContent(model.getContent()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + return record; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/ServerAlarmRuleMapper.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/ServerAlarmRuleMapper.java new file mode 100644 index 0000000000..3f77a94e6c --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/ServerAlarmRuleMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.server.alarm.rule.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.server.alarm.rule.dao.data.ServerAlarmRuleDO; + +public interface ServerAlarmRuleMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + ServerAlarmRuleDO findByPrimaryKey(@Param("id") Long id); + + int insert(ServerAlarmRuleDO record); + + List queryAll(); + + int updateByPrimaryKey(ServerAlarmRuleDO record); + + List findAll(@Param("record") ServerAlarmRuleDO record); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/data/ServerAlarmRuleDO.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/data/ServerAlarmRuleDO.java new file mode 100644 index 0000000000..b9084610a4 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/server/alarm/rule/dao/data/ServerAlarmRuleDO.java @@ -0,0 +1,66 @@ +package com.dianping.cat.mybatis.server.alarm.rule.dao.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class ServerAlarmRuleDO { + private Long id; + + private String category; + + private String endPoint; + + private String measurement; + + private String tags; + + private String content; + + private String type; + + private String creator; + + private Date createTime; + + private Date updateTime; + + private Long keyId; + + public Date getCreationDate() { + return createTime; + } + + public Date getUpdatetime() { + return updateTime; + } + + public void setCreationDate(Date creationDate) { + createTime = creationDate; + } + + public void setId(Integer id) { + this.id = id == null ? null : id.longValue(); + } + + public void setId(Long id) { + this.id = id; + } + + public void setKeyId(Integer keyId) { + this.keyId = keyId == null ? null : keyId.longValue(); + } + + public void setKeyId(Long keyId) { + this.keyId = keyId; + } + + public void setUpdatetime(Date updatetime) { + updateTime = updatetime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/UserDefineRuleMapper.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/UserDefineRuleMapper.java new file mode 100644 index 0000000000..dbf4ca5001 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/UserDefineRuleMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.user.define.rule.dao; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.user.define.rule.dao.data.UserDefineRuleDO; + +public interface UserDefineRuleMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + UserDefineRuleDO findByPrimaryKey(@Param("id") Long id); + + int insert(UserDefineRuleDO record); + + List queryAll(); + + int updateByPrimaryKey(UserDefineRuleDO record); + + List findMaxId(@Param("record") UserDefineRuleDO record); +} diff --git a/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/data/UserDefineRuleDO.java b/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/data/UserDefineRuleDO.java new file mode 100644 index 0000000000..0b144da653 --- /dev/null +++ b/cat-alarm/src/main/java/com/dianping/cat/mybatis/user/define/rule/dao/data/UserDefineRuleDO.java @@ -0,0 +1,52 @@ +package com.dianping.cat.mybatis.user.define.rule.dao.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class UserDefineRuleDO { + private Long id; + + private String content; + + private Date createTime; + + private Date updateTime; + + private Long maxId; + + private Long keyId; + + public Date getCreationDate() { + return createTime; + } + + public void setCreationDate(Date creationDate) { + createTime = creationDate; + } + + public void setId(Integer id) { + this.id = id == null ? null : id.longValue(); + } + + public void setId(Long id) { + this.id = id; + } + + public void setKeyId(Integer keyId) { + this.keyId = keyId == null ? null : keyId.longValue(); + } + + public void setKeyId(Long keyId) { + this.keyId = keyId; + } + + public void setMaxId(Integer maxId) { + this.maxId = maxId == null ? null : maxId.longValue(); + } + + public void setMaxId(Long maxId) { + this.maxId = maxId; + } +} diff --git a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-codegen.xml deleted file mode 100644 index 6b5368fae1..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-codegen.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - FROM - WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-dal.xml b/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-dal.xml deleted file mode 100644 index 9b91486b73..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-dal.xml +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - FROM
- WHERE >= ${start-time} - AND <= ${end-time} - - AND = ${domain} - - ORDER BY desc - ]]> - - - - - - - - FROM
- WHERE >= ${start-time} - AND <= ${end-time} - - AND = ${domain} - - AND in ${categories} - ORDER BY desc - ]]> - - - - - - - - FROM
- WHERE >= ${start-time} - AND <= ${end-time} - - AND = ${category} - - - AND = ${domain} - - ORDER BY asc - ]]> - - - - - - - FROM
- WHERE >= ${start-time} - AND <= ${end-time} - - AND = ${category} - - ORDER BY asc - ]]> - - - - - - - - - - - - - - - FROM
- ]]> - - - - - - - - - - FROM
- ]]> - - - - \ No newline at end of file diff --git a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-manifest.xml deleted file mode 100644 index c0ba94caba..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/jdbc/alarm-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-codegen.xml deleted file mode 100644 index cf2eca960b..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-codegen.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-manifest.xml deleted file mode 100644 index 56a641db3c..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-model.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-model.xml deleted file mode 100644 index 830255b107..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-policy-model.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-codegen.xml deleted file mode 100644 index e087edf599..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-codegen.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-manifest.xml deleted file mode 100644 index 6e0178c847..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-model.xml b/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-model.xml deleted file mode 100644 index 01dca8e96a..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/alert-receiver-model.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-codegen.xml deleted file mode 100644 index f8d095fd1f..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-codegen.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml deleted file mode 100644 index 9e58540d66..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-model.xml b/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-model.xml deleted file mode 100644 index e3aecc329e..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/monitor-rules-model.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-codegen.xml deleted file mode 100644 index 5ea2064b0e..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-codegen.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-manifest.xml deleted file mode 100644 index b97718d367..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-model.xml b/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-model.xml deleted file mode 100644 index 3b03a82d0e..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/sender-config-model.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-codegen.xml b/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-codegen.xml deleted file mode 100644 index 28f49e962a..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-codegen.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-manifest.xml b/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-manifest.xml deleted file mode 100644 index b24907b32e..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-model.xml b/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-model.xml deleted file mode 100644 index baa7f0c329..0000000000 --- a/cat-alarm/src/main/resources/META-INF/dal/model/server-alarm-rule-model.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/plexus/components.xml b/cat-alarm/src/main/resources/META-INF/plexus/components.xml deleted file mode 100644 index abac527c05..0000000000 --- a/cat-alarm/src/main/resources/META-INF/plexus/components.xml +++ /dev/null @@ -1,206 +0,0 @@ - - - - - org.unidal.dal.jdbc.mapping.TableProvider - alert - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - alert - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - server-alarm-rule - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - server_alarm_rule - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - user-define-rule - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - user_define_rule - cat - - - - com.dianping.cat.alarm.AlertDao - com.dianping.cat.alarm.AlertDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.alarm.ServerAlarmRuleDao - com.dianping.cat.alarm.ServerAlarmRuleDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.alarm.UserDefineRuleDao - com.dianping.cat.alarm.UserDefineRuleDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.alarm.spi.config.SenderConfigManager - com.dianping.cat.alarm.spi.config.SenderConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.alarm.spi.rule.DataChecker - com.dianping.cat.alarm.spi.rule.DefaultDataChecker - - - com.dianping.cat.alarm.spi.decorator.DecoratorManager - com.dianping.cat.alarm.spi.decorator.DecoratorManager - - - com.dianping.cat.alarm.spi.receiver.ContactorManager - com.dianping.cat.alarm.spi.receiver.ContactorManager - - - com.dianping.cat.alarm.spi.config.AlertPolicyManager - com.dianping.cat.alarm.spi.config.AlertPolicyManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.alarm.spi.spliter.Spliter - mail - com.dianping.cat.alarm.spi.spliter.MailSpliter - - - com.dianping.cat.alarm.spi.spliter.Spliter - sms - com.dianping.cat.alarm.spi.spliter.SmsSpliter - - - com.dianping.cat.alarm.spi.spliter.Spliter - weixin - com.dianping.cat.alarm.spi.spliter.WeixinSpliter - - - com.dianping.cat.alarm.spi.spliter.Spliter - dx - com.dianping.cat.alarm.spi.spliter.DXSpliter - - - com.dianping.cat.alarm.spi.spliter.SpliterManager - com.dianping.cat.alarm.spi.spliter.SpliterManager - - - com.dianping.cat.alarm.spi.sender.Sender - mail - com.dianping.cat.alarm.spi.sender.MailSender - - - com.dianping.cat.alarm.spi.config.SenderConfigManager - - - - - com.dianping.cat.alarm.spi.sender.Sender - sms - com.dianping.cat.alarm.spi.sender.SmsSender - - - com.dianping.cat.alarm.spi.config.SenderConfigManager - - - - - com.dianping.cat.alarm.spi.sender.Sender - weixin - com.dianping.cat.alarm.spi.sender.WeixinSender - - - com.dianping.cat.alarm.spi.config.SenderConfigManager - - - - - com.dianping.cat.alarm.spi.sender.SenderManager - com.dianping.cat.alarm.spi.sender.SenderManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.alarm.spi.AlertManager - com.dianping.cat.alarm.spi.AlertManager - - - com.dianping.cat.alarm.spi.spliter.SpliterManager - - - com.dianping.cat.alarm.spi.sender.SenderManager - - - com.dianping.cat.alarm.service.AlertService - - - com.dianping.cat.alarm.spi.config.AlertPolicyManager - - - com.dianping.cat.alarm.spi.decorator.DecoratorManager - - - com.dianping.cat.alarm.spi.receiver.ContactorManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.alarm.service.AlertService - com.dianping.cat.alarm.service.AlertService - - - com.dianping.cat.alarm.AlertDao - - - - - com.dianping.cat.alarm.spi.config.AlertConfigManager - com.dianping.cat.alarm.spi.config.AlertConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - diff --git a/cat-alarm/src/main/resources/META-INF/wizard/jdbc/wizard.xml b/cat-alarm/src/main/resources/META-INF/wizard/jdbc/wizard.xml index 9e08c7e17d..dc283842bf 100644 --- a/cat-alarm/src/main/resources/META-INF/wizard/jdbc/wizard.xml +++ b/cat-alarm/src/main/resources/META-INF/wizard/jdbc/wizard.xml @@ -2,7 +2,7 @@ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://127.0.0.1:3306/cat root @@ -10,8 +10,8 @@
-
-
+
+
diff --git a/cat-alarm/src/main/resources/mybatis/mapper/AlertMapper.xml b/cat-alarm/src/main/resources/mybatis/mapper/AlertMapper.xml new file mode 100644 index 0000000000..927922b7b5 --- /dev/null +++ b/cat-alarm/src/main/resources/mybatis/mapper/AlertMapper.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + id , + domain , + alert_time , + category , + type , + content , + metric , + create_time , + update_time + + + + + id = #{id} , + domain = #{domain} , + alert_time = #{alertTime} , + category = #{category} , + type = #{type} , + content = #{content} , + metric = #{metric} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_alert + + + + + + + + + delete from t_alert where id = #{id} + + + + UPDATE t_alert + + WHERE id = #{id} + + + + + + + + + + + diff --git a/cat-alarm/src/main/resources/mybatis/mapper/ServerAlarmRuleMapper.xml b/cat-alarm/src/main/resources/mybatis/mapper/ServerAlarmRuleMapper.xml new file mode 100644 index 0000000000..db8a4a056e --- /dev/null +++ b/cat-alarm/src/main/resources/mybatis/mapper/ServerAlarmRuleMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + id , + category , + endpoint , + measurement , + tags , + content , + type , + creator , + create_time , + update_time + + + + + id = #{id} , + category = #{category} , + endpoint = #{endPoint} , + measurement = #{measurement} , + tags = #{tags} , + content = #{content} , + type = #{type} , + creator = #{creator} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_server_alarm_rule + + + + + + + + + delete from t_server_alarm_rule where id = #{id} + + + + UPDATE t_server_alarm_rule + + WHERE id = #{id} + + + + + diff --git a/cat-alarm/src/main/resources/mybatis/mapper/UserDefineRuleMapper.xml b/cat-alarm/src/main/resources/mybatis/mapper/UserDefineRuleMapper.xml new file mode 100644 index 0000000000..55729142c6 --- /dev/null +++ b/cat-alarm/src/main/resources/mybatis/mapper/UserDefineRuleMapper.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + id , + content , + create_time , + update_time + + + + + id = #{id} , + content = #{content} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_user_define_rule + + + + + + + + + delete from t_user_define_rule where id = #{id} + + + + UPDATE t_user_define_rule + + WHERE id = #{id} + + + + + diff --git a/cat-boot/pom.xml b/cat-boot/pom.xml new file mode 100644 index 0000000000..d28e0227c7 --- /dev/null +++ b/cat-boot/pom.xml @@ -0,0 +1,111 @@ + + + + com.dianping.cat + parent + 4.0-RC1 + + 4.0.0 + cat-boot + cat-boot + jar + + + + org.springframework.boot + spring-boot + ${spring-boot.version} + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat9.version} + + + org.apache.tomcat.embed + tomcat-embed-jasper + ${tomcat9.version} + + + ch.qos.logback + logback-classic + + + org.slf4j + log4j-over-slf4j + + + org.slf4j + jul-to-slf4j + + + com.dianping.cat + cat-home + war + runtime + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.9.0 + + + copy-cat-home-war + process-resources + + copy + + + + + com.dianping.cat + cat-home + ${project.version} + war + ${project.build.outputDirectory} + cat-home.war + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + false + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + com.dianping.cat.boot.CatBootApplication + + + + + + + + + diff --git a/cat-boot/src/main/java/com/dianping/cat/boot/CatBootApplication.java b/cat-boot/src/main/java/com/dianping/cat/boot/CatBootApplication.java new file mode 100644 index 0000000000..d3ab1e5daa --- /dev/null +++ b/cat-boot/src/main/java/com/dianping/cat/boot/CatBootApplication.java @@ -0,0 +1,49 @@ +package com.dianping.cat.boot; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.slf4j.bridge.SLF4JBridgeHandler; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootConfiguration +@ComponentScan(basePackages = "com.dianping.cat.boot") +public class CatBootApplication { + + public static void main(String[] args) throws Exception { + applyDefaultCatProperties(); + routeJavaUtilLoggingToSlf4j(); + SpringApplication.run(CatBootApplication.class, args); + new EmbeddedCatServer().start(); + } + + private static void applyDefaultCatProperties() throws Exception { + String catHome = System.getProperty("cat.home"); + String legacyCatHome = System.getProperty("CAT_HOME"); + + if (catHome == null || catHome.isBlank()) { + catHome = legacyCatHome == null || legacyCatHome.isBlank() + ? Paths.get(System.getProperty("user.home"), ".cat").toString() + : legacyCatHome; + System.setProperty("cat.home", catHome); + } + + if (legacyCatHome == null || legacyCatHome.isBlank()) { + System.setProperty("CAT_HOME", catHome); + } + + if (System.getProperty("cat.log.path") == null || System.getProperty("cat.log.path").isBlank()) { + System.setProperty("cat.log.path", Paths.get(catHome, "logs").toString()); + } + + Files.createDirectories(Path.of(System.getProperty("cat.log.path"))); + } + + private static void routeJavaUtilLoggingToSlf4j() { + SLF4JBridgeHandler.removeHandlersForRootLogger(); + SLF4JBridgeHandler.install(); + } +} diff --git a/cat-boot/src/main/java/com/dianping/cat/boot/EmbeddedCatServer.java b/cat-boot/src/main/java/com/dianping/cat/boot/EmbeddedCatServer.java new file mode 100644 index 0000000000..5cb3156f31 --- /dev/null +++ b/cat-boot/src/main/java/com/dianping/cat/boot/EmbeddedCatServer.java @@ -0,0 +1,117 @@ +package com.dianping.cat.boot; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.catalina.Context; +import org.apache.catalina.startup.Tomcat; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EmbeddedCatServer { + private static final Logger LOGGER = LoggerFactory.getLogger(EmbeddedCatServer.class); + + private static final String WAR_RESOURCE = "cat-home.war"; + + private static final String CONTEXT_PATH = "/cat"; + + public void start() throws IOException { + int port = Integer.parseInt(System.getProperty("server.port", "8080")); + Path baseDir = resolveBaseDir(port); + deleteDirectory(baseDir); + Path appBase = Files.createDirectories(baseDir.resolve("webapps")); + Path webapp = resolveWebapp(baseDir); + + Tomcat tomcat = new Tomcat(); + tomcat.setBaseDir(baseDir.toString()); + tomcat.setPort(port); + tomcat.getConnector().setURIEncoding("UTF-8"); + tomcat.getHost().setAppBase(appBase.toString()); + + LOGGER.info("Starting CAT web application, contextPath={}, webapp={}.", CONTEXT_PATH, webapp); + Context context = tomcat.addWebapp(CONTEXT_PATH, webapp.toString()); + context.setParentClassLoader(getClass().getClassLoader()); + + try { + tomcat.start(); + tomcat.getServer().await(); + } catch (Exception e) { + throw new IllegalStateException("Failed to start embedded CAT web application.", e); + } + } + + private Path copyWar(Path baseDir) throws IOException { + Path warFile = baseDir.resolve(WAR_RESOURCE); + + try (InputStream input = getClass().getClassLoader().getResourceAsStream(WAR_RESOURCE)) { + if (input == null) { + throw new IllegalStateException("Missing " + WAR_RESOURCE + " on classpath."); + } + Files.copy(input, warFile); + } + + return warFile; + } + + private Path defaultExplodedWebapp() { + Path fromRepositoryRoot = Paths.get("cat-home", "target", "cat-home").toAbsolutePath().normalize(); + + if (Files.exists(fromRepositoryRoot.resolve("WEB-INF").resolve("web.xml"))) { + return fromRepositoryRoot; + } + return Paths.get("..", "cat-home", "target", "cat-home").toAbsolutePath().normalize(); + } + + private void deleteDirectory(Path directory) throws IOException { + if (!Files.exists(directory)) { + return; + } + + try (java.util.stream.Stream paths = Files.walk(directory)) { + paths.sorted(java.util.Comparator.reverseOrder()).forEach(path -> { + try { + Files.deleteIfExists(path); + } catch (IOException e) { + throw new IllegalStateException("Unable to clean CAT boot directory: " + directory, e); + } + }); + } catch (IllegalStateException e) { + if (e.getCause() instanceof IOException) { + throw (IOException) e.getCause(); + } + throw e; + } + } + + private Path resolveBaseDir(int port) { + String configuredBaseDir = System.getProperty("cat.boot.baseDir"); + + if (configuredBaseDir != null && configuredBaseDir.trim().length() > 0) { + return Paths.get(configuredBaseDir).toAbsolutePath().normalize(); + } + return Paths.get("target", "cat-boot-" + port).toAbsolutePath().normalize(); + } + + private Path resolveWebapp(Path baseDir) throws IOException { + String configuredWebapp = System.getProperty("cat.home.webapp"); + + if (configuredWebapp != null && configuredWebapp.trim().length() > 0) { + Path webapp = Paths.get(configuredWebapp).toAbsolutePath().normalize(); + + if (!Files.exists(webapp)) { + throw new IllegalStateException("Configured CAT home webapp does not exist: " + webapp); + } + return webapp; + } + + Path explodedWebapp = defaultExplodedWebapp(); + + if (Files.exists(explodedWebapp.resolve("WEB-INF").resolve("web.xml"))) { + return explodedWebapp; + } + return copyWar(baseDir); + } +} diff --git a/cat-boot/src/main/java/com/dianping/cat/boot/config/CatSpringStartupVerifier.java b/cat-boot/src/main/java/com/dianping/cat/boot/config/CatSpringStartupVerifier.java new file mode 100644 index 0000000000..fb088091cd --- /dev/null +++ b/cat-boot/src/main/java/com/dianping/cat/boot/config/CatSpringStartupVerifier.java @@ -0,0 +1,25 @@ +package com.dianping.cat.boot.config; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +@Component +public class CatSpringStartupVerifier implements ApplicationRunner { + private static final Logger LOGGER = LoggerFactory.getLogger(CatSpringStartupVerifier.class); + + private final ApplicationContext m_applicationContext; + + public CatSpringStartupVerifier(ApplicationContext applicationContext) { + m_applicationContext = applicationContext; + } + + @Override + public void run(org.springframework.boot.ApplicationArguments args) { + LOGGER.info("Spring context initialized, id={}, cat.home={}, cat.log.path={}, server.port={}", + m_applicationContext.getId(), System.getProperty("cat.home"), System.getProperty("cat.log.path"), + System.getProperty("server.port", "8080")); + } +} diff --git a/cat-boot/src/main/resources/logback.xml b/cat-boot/src/main/resources/logback.xml new file mode 100644 index 0000000000..e7f172da3d --- /dev/null +++ b/cat-boot/src/main/resources/logback.xml @@ -0,0 +1,145 @@ + + + cat-boot + + + + + + + + + ${CAT_CONSOLE_LEVEL:-INFO} + + + ${CONSOLE_LOG_PATTERN} + UTF-8 + + + + + ${LOG_HOME}/debug.log + + ${FILE_LOG_PATTERN} + UTF-8 + + + ${LOG_HOME}/debug-%d{yyyy-MM-dd}.%i.log.gz + 200MB + 7 + 20GB + true + + + DEBUG + ACCEPT + DENY + + + + + ${LOG_HOME}/info.log + + ${FILE_LOG_PATTERN} + UTF-8 + + + ${LOG_HOME}/info-%d{yyyy-MM-dd}.%i.log.gz + 200MB + 30 + 20GB + true + + + INFO + + + + + ${LOG_HOME}/warn.log + true + + ${FILE_LOG_PATTERN} + UTF-8 + + + ${LOG_HOME}/warn-%d{yyyy-MM-dd}.%i.log.gz + 200MB + 30 + 10GB + true + + + WARN + ACCEPT + DENY + + + + + ${LOG_HOME}/error.log + true + + ${FILE_LOG_PATTERN} + UTF-8 + + + ${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.log.gz + 200MB + 30 + 10GB + true + + + ERROR + ACCEPT + DENY + + + + + false + 8192 + 20 + true + + + + + false + 8192 + 0 + false + + + + + false + 4096 + 0 + true + + + + + true + 4096 + 0 + true + + + + + + + + + + + + + + + diff --git a/cat-client/pom.xml b/cat-client/pom.xml index 0a4015ec5f..edee9247dc 100644 --- a/cat-client/pom.xml +++ b/cat-client/pom.xml @@ -39,11 +39,10 @@ - - org.apache.maven.plugins - maven-shade-plugin - 3.3.0 - + + org.apache.maven.plugins + maven-shade-plugin + package @@ -70,30 +69,7 @@ - - + diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/BaseEntity.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/BaseEntity.java index 62449f88a1..1b184a1d2e 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/BaseEntity.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/BaseEntity.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model; import java.util.Formattable; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/ClientConfigHelper.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/ClientConfigHelper.java index 2d65870575..2dc39dcfaf 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/ClientConfigHelper.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/ClientConfigHelper.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model; import java.io.BufferedInputStream; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/Constants.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/Constants.java index a31240037b..1700a897fb 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/Constants.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/Constants.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model; public class Constants { diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/IEntity.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/IEntity.java index 8c9a278a4e..3cac9c9c95 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/IEntity.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/IEntity.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model; public interface IEntity { diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/IVisitor.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/IVisitor.java index 08a780cdcf..368219740c 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/IVisitor.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/IVisitor.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model; import com.dianping.cat.configuration.model.entity.ClientConfig; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/ClientConfig.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/ClientConfig.java index edce8145f8..a3fd823491 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/ClientConfig.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/ClientConfig.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.entity; import java.util.ArrayList; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Domain.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Domain.java index 93068262cd..8a3d33f66b 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Domain.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Domain.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.entity; import java.util.LinkedHashMap; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Host.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Host.java index 8763293546..185eee1541 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Host.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Host.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.entity; import com.dianping.cat.configuration.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Property.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Property.java index c4332b2bb7..8214c2337f 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Property.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Property.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.entity; import static com.dianping.cat.configuration.model.Constants.ATTR_NAME; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Server.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Server.java index 6f0ed9d154..3199de0c79 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Server.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/entity/Server.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.entity; import static com.dianping.cat.configuration.model.Constants.ATTR_IP; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/BaseVisitor.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/BaseVisitor.java index bb95cbba5f..a0413c3b69 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/BaseVisitor.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/BaseVisitor.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.transform; import com.dianping.cat.configuration.model.IVisitor; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultLinker.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultLinker.java index 729c4a4242..9c39ea28b2 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultLinker.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultLinker.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.transform; import java.util.ArrayList; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlBuilder.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlBuilder.java index 651e6fe3d6..18dce7bbe4 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlBuilder.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlBuilder.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.transform; import static com.dianping.cat.configuration.model.Constants.ATTR_ENABLED; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlMaker.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlMaker.java index f179bdeecf..e5e643950d 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlMaker.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlMaker.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.transform; import static com.dianping.cat.configuration.model.Constants.ATTR_ENABLED; diff --git a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlParser.java b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlParser.java index ee353a5673..e443a14511 100644 --- a/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlParser.java +++ b/cat-client/src/main/java/com/dianping/cat/configuration/model/transform/DefaultXmlParser.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.configuration.model.transform; diff --git a/cat-client/src/main/java/com/dianping/cat/message/internal/DefaultTransaction.java b/cat-client/src/main/java/com/dianping/cat/message/internal/DefaultTransaction.java index 77415174d5..3cc454e15a 100644 --- a/cat-client/src/main/java/com/dianping/cat/message/internal/DefaultTransaction.java +++ b/cat-client/src/main/java/com/dianping/cat/message/internal/DefaultTransaction.java @@ -136,7 +136,8 @@ public List getChildren() { @Override public long getDurationInMicros() { - if (super.isCompleted()) { + // 解码出来的 transaction 没有运行中的 TraceContext,但已经带有编码后的耗时。 + if (super.isCompleted() || (m_ctx == null && m_durationInMicros > 0)) { return m_durationInMicros; } else { return 0; @@ -145,7 +146,8 @@ public long getDurationInMicros() { @Override public long getDurationInMillis() { - if (super.isCompleted()) { + // 解码出来的 transaction 没有运行中的 TraceContext,但已经带有编码后的耗时。 + if (super.isCompleted() || (m_ctx == null && m_durationInMicros > 0)) { return m_durationInMicros / 1000L; } else { return 0; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/BaseEntity.java b/cat-client/src/main/java/com/dianping/cat/status/model/BaseEntity.java index be49009095..5a9a7fe1b5 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/BaseEntity.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/BaseEntity.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model; import java.util.Formattable; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/Constants.java b/cat-client/src/main/java/com/dianping/cat/status/model/Constants.java index 884e53685e..14fcbb39e5 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/Constants.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/Constants.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model; public class Constants { diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/IEntity.java b/cat-client/src/main/java/com/dianping/cat/status/model/IEntity.java index 419e36927b..e13884169a 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/IEntity.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/IEntity.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model; public interface IEntity { diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/IVisitor.java b/cat-client/src/main/java/com/dianping/cat/status/model/IVisitor.java index 423f6f3617..2f01407b84 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/IVisitor.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/IVisitor.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model; import com.dianping.cat.status.model.entity.DiskInfo; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/StatusInfoHelper.java b/cat-client/src/main/java/com/dianping/cat/status/model/StatusInfoHelper.java index defdd84b16..465a6a7d61 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/StatusInfoHelper.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/StatusInfoHelper.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model; import java.io.BufferedInputStream; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskInfo.java index d956979a73..22159c179d 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import java.util.ArrayList; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskVolumeInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskVolumeInfo.java index 66d1ea48e6..4dd1f46862 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskVolumeInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/DiskVolumeInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import static com.dianping.cat.status.model.Constants.ATTR_ID; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/Extension.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/Extension.java index ffce6768d6..cf5935300c 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/Extension.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/Extension.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import static com.dianping.cat.status.model.Constants.ATTR_ID; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/ExtensionDetail.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/ExtensionDetail.java index 768fdd0d2c..3c3709201e 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/ExtensionDetail.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/ExtensionDetail.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import static com.dianping.cat.status.model.Constants.ATTR_ID; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/GcInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/GcInfo.java index 338da6c3b4..4599440e2c 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/GcInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/GcInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import com.dianping.cat.status.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/MemoryInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/MemoryInfo.java index 381972dc9a..a948abc902 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/MemoryInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/MemoryInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import java.util.ArrayList; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/MessageInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/MessageInfo.java index 33900e2a65..f625657863 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/MessageInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/MessageInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import com.dianping.cat.status.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/OsInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/OsInfo.java index e35ec729a3..18d1862846 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/OsInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/OsInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import com.dianping.cat.status.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/RuntimeInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/RuntimeInfo.java index ccf65ced17..81a334c26a 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/RuntimeInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/RuntimeInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import com.dianping.cat.status.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/StatusInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/StatusInfo.java index a59a7a5bfe..33cb65c54d 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/StatusInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/StatusInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import java.util.LinkedHashMap; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/entity/ThreadsInfo.java b/cat-client/src/main/java/com/dianping/cat/status/model/entity/ThreadsInfo.java index 230686ba94..ccdff075c0 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/entity/ThreadsInfo.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/entity/ThreadsInfo.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.entity; import com.dianping.cat.status.model.BaseEntity; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/transform/BaseVisitor.java b/cat-client/src/main/java/com/dianping/cat/status/model/transform/BaseVisitor.java index b934dc0c08..8993988693 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/transform/BaseVisitor.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/transform/BaseVisitor.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.transform; import com.dianping.cat.status.model.IVisitor; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultLinker.java b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultLinker.java index 7f1745e37d..6edb0c97b4 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultLinker.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultLinker.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.transform; import java.util.ArrayList; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlBuilder.java b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlBuilder.java index 363fbf842b..933975d71d 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlBuilder.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlBuilder.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.transform; import static com.dianping.cat.status.model.Constants.ATTR_ARCH; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlMaker.java b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlMaker.java index 8543cd4975..b6781a723d 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlMaker.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlMaker.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.transform; import static com.dianping.cat.status.model.Constants.ATTR_ARCH; diff --git a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlParser.java b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlParser.java index e7bbb09321..d8f56e9792 100644 --- a/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlParser.java +++ b/cat-client/src/main/java/com/dianping/cat/status/model/transform/DefaultXmlParser.java @@ -1,4 +1,3 @@ -/* THIS FILE WAS AUTO GENERATED BY codegen-maven-plugin, DO NOT EDIT IT */ package com.dianping.cat.status.model.transform; import static com.dianping.cat.status.model.Constants.ELEMENT_DESCRIPTION; diff --git a/cat-client/src/test/java/com/dianping/cat/CatBootstrapTest.java b/cat-client/src/test/java/com/dianping/cat/CatBootstrapTest.java index 9fb3e2279a..eaddc3f688 100644 --- a/cat-client/src/test/java/com/dianping/cat/CatBootstrapTest.java +++ b/cat-client/src/test/java/com/dianping/cat/CatBootstrapTest.java @@ -7,7 +7,7 @@ import com.dianping.cat.configuration.ConfigureManager; -public class CatBootstrapTest extends ComponentTestCase { +public class CatBootstrapTest extends CatClientTestSupport { @After public void after() { } @@ -20,7 +20,7 @@ public void before() { public void testInitializeByDomain() { Cat.getBootstrap().initializeByDomain("MyDomain"); - ConfigureManager manager = context().lookup(ConfigureManager.class); + ConfigureManager manager = componentContext().lookup(ConfigureManager.class); Assert.assertEquals("MyDomain", manager.getDomain()); } @@ -29,7 +29,7 @@ public void testInitializeByDomain() { public void testInitializeByDomainAndServers() { Cat.getBootstrap().initializeByDomain("MyDomain", "server1", "server2"); - ConfigureManager manager = context().lookup(ConfigureManager.class); + ConfigureManager manager = componentContext().lookup(ConfigureManager.class); Assert.assertEquals("MyDomain", manager.getDomain()); Assert.assertEquals(2, manager.getServers().size()); @@ -41,7 +41,7 @@ public void testInitializeByDomainAndServers() { public void testInitializeByServers() { Cat.getBootstrap().initialize("server1", "server2"); - ConfigureManager manager = context().lookup(ConfigureManager.class); + ConfigureManager manager = componentContext().lookup(ConfigureManager.class); Assert.assertEquals(2, manager.getServers().size()); Assert.assertEquals("server1", manager.getServers().get(0).getIp()); diff --git a/cat-client/src/test/java/com/dianping/cat/CatClientTestSupport.java b/cat-client/src/test/java/com/dianping/cat/CatClientTestSupport.java new file mode 100644 index 0000000000..5d4b76f73c --- /dev/null +++ b/cat-client/src/test/java/com/dianping/cat/CatClientTestSupport.java @@ -0,0 +1,29 @@ +package com.dianping.cat; + +import org.junit.After; +import org.junit.Before; + +import com.dianping.cat.component.ComponentContext; +import com.dianping.cat.message.context.MetricContextHelper; +import com.dianping.cat.message.context.TraceContextHelper; + +public abstract class CatClientTestSupport { + protected ComponentContext componentContext() { + return Cat.getBootstrap().getComponentContext(); + } + + @Before + public void setUp() throws Exception { + Cat.destroy(); + Cat.getBootstrap().testMode(); + TraceContextHelper.reset(); + MetricContextHelper.reset(); + } + + @After + public void tearDown() throws Exception { + Cat.destroy(); + TraceContextHelper.reset(); + MetricContextHelper.reset(); + } +} diff --git a/cat-client/src/test/java/com/dianping/cat/ComponentTestCase.java b/cat-client/src/test/java/com/dianping/cat/ComponentTestCase.java deleted file mode 100644 index 9cdce81afe..0000000000 --- a/cat-client/src/test/java/com/dianping/cat/ComponentTestCase.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.dianping.cat; - -import org.junit.After; -import org.junit.Before; - -import com.dianping.cat.component.ComponentContext; -import com.dianping.cat.message.context.MetricContextHelper; -import com.dianping.cat.message.context.TraceContextHelper; - -public abstract class ComponentTestCase { - protected ComponentContext context() { - return Cat.getBootstrap().getComponentContext(); - } - - protected T lookup(Class componentType) { - return context().lookup(componentType); - } - - @Before - public void setUp() throws Exception { - Cat.destroy(); - Cat.getBootstrap().testMode(); - TraceContextHelper.reset(); - MetricContextHelper.reset(); - } - - @After - public void tearDown() throws Exception { - Cat.destroy(); - TraceContextHelper.reset(); - MetricContextHelper.reset(); - } -} diff --git a/cat-client/src/test/java/com/dianping/cat/configuration/ConfigureManagerTest.java b/cat-client/src/test/java/com/dianping/cat/configuration/ConfigureManagerTest.java index a41820c4f9..8a34d66000 100644 --- a/cat-client/src/test/java/com/dianping/cat/configuration/ConfigureManagerTest.java +++ b/cat-client/src/test/java/com/dianping/cat/configuration/ConfigureManagerTest.java @@ -3,19 +3,18 @@ import org.junit.Assert; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; import com.dianping.cat.component.ComponentContext; import com.dianping.cat.component.DefaultComponentContext; import com.dianping.cat.component.factory.CatComponentFactory; -public class ConfigureManagerTest extends ComponentTestCase { +public class ConfigureManagerTest { @Test public void testConfigureManager() { ComponentContext ctx = new DefaultComponentContext(); ctx.registerFactory(new CatComponentFactory()); - ConfigureManager manager = lookup(ConfigureManager.class); + ConfigureManager manager = ctx.lookup(ConfigureManager.class); Assert.assertNotNull(manager); } diff --git a/cat-client/src/test/java/com/dianping/cat/message/MessageTest.java b/cat-client/src/test/java/com/dianping/cat/message/MessageTest.java index 058ba334bc..66969dfb6e 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/MessageTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/MessageTest.java @@ -18,14 +18,14 @@ import org.junit.Test; import com.dianping.cat.Cat; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.message.MessageAssert.TransactionAssert; import com.dianping.cat.message.context.MessageIdFactory; import com.dianping.cat.message.context.TraceContextHelper; import com.dianping.cat.message.internal.DefaultForkedTransaction; import com.dianping.cat.message.internal.DefaultTransaction; -public class MessageTest extends ComponentTestCase { +public class MessageTest extends CatClientTestSupport { private static AtomicInteger s_index = new AtomicInteger(); private static AtomicInteger s_count = new AtomicInteger(); @@ -41,9 +41,9 @@ public void after() { public void before() throws Exception { Cat.getBootstrap().testMode(); - MessageAssert.intercept(context()); + MessageAssert.intercept(componentContext()); - context().registerComponent(MessageIdFactory.class, new MockMessageIdFactory()); + componentContext().registerComponent(MessageIdFactory.class, new MockMessageIdFactory()); } private void checkMessageIdUsed(int expected) throws InterruptedException { diff --git a/cat-client/src/test/java/com/dianping/cat/message/MetricTest.java b/cat-client/src/test/java/com/dianping/cat/message/MetricTest.java index 2efa00be32..4ce348b824 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/MetricTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/MetricTest.java @@ -5,10 +5,10 @@ import org.junit.Test; import com.dianping.cat.Cat; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.message.Metric.Kind; -public class MetricTest extends ComponentTestCase { +public class MetricTest extends CatClientTestSupport { @After public void after() { MetricAssert.reset(); @@ -18,7 +18,7 @@ public void after() { public void before() throws Exception { Cat.getBootstrap().testMode(); - MetricAssert.intercept(context()); + MetricAssert.intercept(componentContext()); } @Test diff --git a/cat-client/src/test/java/com/dianping/cat/message/context/MessageContextTest.java b/cat-client/src/test/java/com/dianping/cat/message/context/MessageContextTest.java index ad8423c405..73028a7ae7 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/context/MessageContextTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/context/MessageContextTest.java @@ -2,14 +2,25 @@ import javax.servlet.http.HttpServletRequest; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; import com.dianping.cat.message.Transaction; -public class MessageContextTest extends ComponentTestCase { +public class MessageContextTest { + @Before + public void setUp() { + TraceContextHelper.reset(); + } + + @After + public void tearDown() { + TraceContextHelper.reset(); + } + @Test public void testInstrument() { int index = 1; diff --git a/cat-client/src/test/java/com/dianping/cat/message/context/MessageIdFactoryTest.java b/cat-client/src/test/java/com/dianping/cat/message/context/MessageIdFactoryTest.java index 255fe11979..d6e85e3989 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/context/MessageIdFactoryTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/context/MessageIdFactoryTest.java @@ -19,11 +19,10 @@ import org.junit.Assert; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; import com.dianping.cat.support.Files; import com.dianping.cat.support.Threads; -public class MessageIdFactoryTest extends ComponentTestCase { +public class MessageIdFactoryTest { /** * Run it multiple times in console to simulate multiple processes scenario, * @@ -53,9 +52,7 @@ public static void main(String... args) throws Exception { @Test public void testDefaultDomain() throws IOException { - File baseDir = new File("target/mark"); - - new File(baseDir, "default-domain.mark").delete(); + File baseDir = newMarkDir("default-domain"); MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-domain"); @@ -66,9 +63,7 @@ public void testDefaultDomain() throws IOException { @Test public void testGivenDomain() throws IOException { - File baseDir = new File("target/mark"); - - new File(baseDir, "given-domain.mark").delete(); + File baseDir = newMarkDir("given-domain"); MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-domain"); @@ -79,9 +74,7 @@ public void testGivenDomain() throws IOException { @Test public void testDefaultDomainInParallel() throws Exception { - File baseDir = new File("target/mark"); - - new File(baseDir, "default-parallel.mark").delete(); + File baseDir = newMarkDir("default-parallel"); final MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-parallel"); final Set ids = Collections.synchronizedSet(new HashSet()); @@ -101,10 +94,11 @@ public void run() { } pool.shutdown(); - pool.awaitTermination(2000, TimeUnit.MILLISECONDS); + boolean completed = pool.awaitTermination(30, TimeUnit.SECONDS); int total = threads * messagesPerThread; + Assert.assertTrue("Not all threads completed in time.", completed); Assert.assertEquals("Not all threads completed in time.", total, ids.size()); Assert.assertEquals(true, ids.contains(String.format("default-parallel-c0a81f9e-403215-%s", total - 1))); Assert.assertEquals(String.format("default-parallel-c0a81f9e-403215-%s", total), factory.getNextId()); @@ -112,9 +106,7 @@ public void run() { @Test public void testGivenDomainInParallel() throws Exception { - File baseDir = new File("target/mark"); - - new File(baseDir, "given-parallel.mark").delete(); + File baseDir = newMarkDir("given-parallel"); final MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-parallel"); final Set ids = Collections.synchronizedSet(new HashSet()); @@ -134,10 +126,11 @@ public void run() { } pool.shutdown(); - pool.awaitTermination(2000, TimeUnit.MILLISECONDS); + boolean completed = pool.awaitTermination(30, TimeUnit.SECONDS); int total = threads * messagesPerThread; + Assert.assertTrue("Not all threads completed in time.", completed); Assert.assertEquals("Not all threads completed in time.", total, ids.size()); Assert.assertEquals(true, ids.contains(String.format("given-parallel-c0a81f9e-403215-%s", total - 1))); Assert.assertEquals(String.format("given-parallel-c0a81f9e-403215-%s", total), @@ -146,9 +139,7 @@ public void run() { @Test public void testDefaultDomainResume() throws IOException { - File baseDir = new File("target/mark"); - - new File(baseDir, "default-resume.mark").delete(); + File baseDir = newMarkDir("default-resume"); // first round MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-resume"); @@ -169,9 +160,7 @@ public void testDefaultDomainResume() throws IOException { @Test public void testGivenDomainResume() throws IOException { - File baseDir = new File("target/mark"); - - new File(baseDir, "given-resume.mark").delete(); + File baseDir = newMarkDir("given-resume"); // first round MessageIdFactory factory = new MockMessageIdFactory(baseDir, "default-resume"); @@ -303,4 +292,12 @@ protected String getIpAddress() { return "c0a81f9e"; } } -} \ No newline at end of file + + private File newMarkDir(String name) { + File baseDir = new File("target/mark/" + name); + + Files.forDir().delete(baseDir, true); + + return baseDir; + } +} diff --git a/cat-client/src/test/java/com/dianping/cat/message/internal/MockMessageBuilderTest.java b/cat-client/src/test/java/com/dianping/cat/message/internal/MockMessageBuilderTest.java index 62b763be0d..d0a2dde846 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/internal/MockMessageBuilderTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/internal/MockMessageBuilderTest.java @@ -21,10 +21,9 @@ import org.junit.Assert; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; import com.dianping.cat.message.Message; -public class MockMessageBuilderTest extends ComponentTestCase { +public class MockMessageBuilderTest { @Test public void test() { Message message = new MockMessageBuilder() { diff --git a/cat-client/src/test/java/com/dianping/cat/message/pipeline/MessagePipelineTest.java b/cat-client/src/test/java/com/dianping/cat/message/pipeline/MessagePipelineTest.java index ab9f3d487f..76fb155a7b 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/pipeline/MessagePipelineTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/pipeline/MessagePipelineTest.java @@ -3,17 +3,17 @@ import org.junit.Assert; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.message.internal.DefaultMessageTree; -public class MessagePipelineTest extends ComponentTestCase { +public class MessagePipelineTest extends CatClientTestSupport { private int m_count; @Test public void test() { - context().registerComponent(MessageHandler.class, new CounterHandler()); + componentContext().registerComponent(MessageHandler.class, new CounterHandler()); - MessagePipeline pipeline = lookup(MessagePipeline.class); + MessagePipeline pipeline = componentContext().lookup(MessagePipeline.class); DefaultMessageTree tree = new DefaultMessageTree(null); MessageHandlerContext ctx = pipeline.headContext(tree); diff --git a/cat-client/src/test/java/com/dianping/cat/message/pipeline/MetricAggregatorTest.java b/cat-client/src/test/java/com/dianping/cat/message/pipeline/MetricAggregatorTest.java index 19c887e056..30659f9e7c 100644 --- a/cat-client/src/test/java/com/dianping/cat/message/pipeline/MetricAggregatorTest.java +++ b/cat-client/src/test/java/com/dianping/cat/message/pipeline/MetricAggregatorTest.java @@ -7,18 +7,18 @@ import org.junit.Test; import com.dianping.cat.Cat; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.message.MetricBag; import com.dianping.cat.message.context.MetricContext; -public class MetricAggregatorTest extends ComponentTestCase { +public class MetricAggregatorTest extends CatClientTestSupport { private AtomicInteger m_count = new AtomicInteger(); private StringBuilder m_sb = new StringBuilder(); @Before public void before() throws Exception { - context().registerComponent(MessageHandler.class, new CounterHandler()); + componentContext().registerComponent(MessageHandler.class, new CounterHandler()); } @Test @@ -31,7 +31,7 @@ public void test() throws InterruptedException { Cat.logMetricForDuration("duration", 200); // trigger metric aggregation - lookup(MessagePipeline.class).headContext(MetricContext.TICK).fireMessage(MetricContext.TICK); + componentContext().lookup(MessagePipeline.class).headContext(MetricContext.TICK).fireMessage(MetricContext.TICK); Assert.assertEquals(1, m_count.get()); diff --git a/cat-client/src/test/java/com/dianping/cat/network/ClientTransportManagerTest.java b/cat-client/src/test/java/com/dianping/cat/network/ClientTransportManagerTest.java index a7d56b2e6b..fdf85180ec 100644 --- a/cat-client/src/test/java/com/dianping/cat/network/ClientTransportManagerTest.java +++ b/cat-client/src/test/java/com/dianping/cat/network/ClientTransportManagerTest.java @@ -10,7 +10,7 @@ import org.junit.Before; import org.junit.Test; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.configuration.ConfigureManager; import com.dianping.cat.configuration.ConfigureProperty; import com.dianping.cat.configuration.DefaultConfigureManager; @@ -23,17 +23,17 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; -public class ClientTransportManagerTest extends ComponentTestCase { +public class ClientTransportManagerTest extends CatClientTestSupport { private List m_ports = new ArrayList<>(); @Before public void before() { - context().registerComponent(ConfigureManager.class, new MockConfigureManager()); + componentContext().registerComponent(ConfigureManager.class, new MockConfigureManager()); } @Test public void testReconfigure() throws Exception { - ClientTransportManager manager = lookup(ClientTransportManager.class); + ClientTransportManager manager = componentContext().lookup(ClientTransportManager.class); Server s2290 = new Server(manager, 2290); Server s2291 = new Server(manager, 2291); Server s2292 = new Server(manager, 2292); diff --git a/cat-client/src/test/java/com/dianping/cat/support/servlet/CatFilterTest.java b/cat-client/src/test/java/com/dianping/cat/support/servlet/CatFilterTest.java index b1236309b1..0598f96c2c 100644 --- a/cat-client/src/test/java/com/dianping/cat/support/servlet/CatFilterTest.java +++ b/cat-client/src/test/java/com/dianping/cat/support/servlet/CatFilterTest.java @@ -45,7 +45,7 @@ import com.dianping.cat.Cat.PropertyConsumer; import com.dianping.cat.Cat.PropertyContext; import com.dianping.cat.CatClientConstants; -import com.dianping.cat.ComponentTestCase; +import com.dianping.cat.CatClientTestSupport; import com.dianping.cat.message.MessageAssert; import com.dianping.cat.message.MessageAssert.HeaderAssert; import com.dianping.cat.message.MessageAssert.TransactionAssert; @@ -57,7 +57,7 @@ import com.github.netty.protocol.HttpServletProtocol; import com.github.netty.protocol.servlet.ServletContext; -public class CatFilterTest extends ComponentTestCase { +public class CatFilterTest extends CatClientTestSupport { private HttpServer m_server; @After @@ -68,7 +68,7 @@ public void after() { @Before public void before() { - MessageAssert.intercept(Cat.getBootstrap().getComponentContext()); + MessageAssert.intercept(componentContext()); Cat.getBootstrap().initializeByDomain("mockApp"); diff --git a/cat-client/src/test/resources/log4j.properties b/cat-client/src/test/resources/log4j.properties new file mode 100644 index 0000000000..42a4b984de --- /dev/null +++ b/cat-client/src/test/resources/log4j.properties @@ -0,0 +1,4 @@ +log4j.rootLogger=WARN, CONSOLE +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] [%-5p] [%c{1}] %m%n diff --git a/cat-consumer/pom.xml b/cat-consumer/pom.xml index fb48f73398..f597bda21f 100644 --- a/cat-consumer/pom.xml +++ b/cat-consumer/pom.xml @@ -15,30 +15,38 @@ com.dianping.cat cat-core - - com.dianping.cat - cat-hadoop - - - org.unidal.framework - test-framework - test - - - com.google.code.gson - gson - test - - - junit - junit - test - - - mysql - mysql-connector-java - runtime + + com.dianping.cat + cat-hadoop + + + org.springframework + spring-context + + + jakarta.annotation + jakarta.annotation-api + + + com.google.code.gson + gson + test + + + ch.qos.logback + logback-classic + test + + + junit + junit + test + + com.mysql + mysql-connector-j + runtime + xmlunit xmlunit @@ -47,55 +55,7 @@ - - - - org.unidal.maven.plugins - codegen-maven-plugin - - - generate report models - generate-sources - - dal-model - - - ${basedir}/src/main/resources/META-INF/dal/model/transaction-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/all-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/event-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/problem-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/heartbeat-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/state-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/top-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/cross-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/matrix-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/dependency-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/storage-report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/business-report-manifest.xml, - - - - - - - org.unidal.maven.plugins - plexus-maven-plugin - - - generate plexus component descriptor - process-classes - - plexus - - - com.dianping.cat.consumer.build.ComponentsConfigurator - - - - - - - + utf-8 diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/CatConsumerModule.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/CatConsumerModule.java deleted file mode 100644 index f90ae2ccd1..0000000000 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/CatConsumerModule.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer; - -import org.unidal.initialization.AbstractModule; -import org.unidal.initialization.Module; -import org.unidal.initialization.ModuleContext; - -import com.dianping.cat.CatCoreModule; - -public class CatConsumerModule extends AbstractModule { - public static final String ID = "cat-consumer"; - - @Override - protected void execute(ModuleContext ctx) { - } - - @Override - public Module[] getDependencies(ModuleContext ctx) { - return ctx.getModules(CatCoreModule.ID); - } -} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/DatabaseParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/DatabaseParser.java index dd70d7d26d..f418bbe330 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/DatabaseParser.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/DatabaseParser.java @@ -23,27 +23,21 @@ import java.util.Map; import java.util.Set; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.util.StringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.message.Event; import com.dianping.cat.message.Transaction; -public class DatabaseParser implements LogEnabled { +public class DatabaseParser { - private Logger m_logger; + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DatabaseParser.class); private Set m_errorConnections = new HashSet(); private Map m_connections = new LinkedHashMap(); - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - public Database parseDatabase(String connection) { Database database = m_connections.get(connection); @@ -81,7 +75,7 @@ public Database parseDatabase(String connection) { m_connections.put(connection, database); } else { m_errorConnections.add(connection); - m_logger.info("Unrecognized jdbc connection string: " + connection); + logUnrecognizedConnection(connection); } } catch (Exception e) { m_errorConnections.add(connection); @@ -103,6 +97,10 @@ public void showErrorCon() { } } + private void logUnrecognizedConnection(String connection) { + LOGGER.warn("Unrecognized jdbc connection string: {}", connection); + } + public static class Database { private String m_name; diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/BaseEntity.java new file mode 100644 index 0000000000..2275930772 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.all.config; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.all.config.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/Constants.java new file mode 100644 index 0000000000..0be1d6a2ac --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/Constants.java @@ -0,0 +1,20 @@ +package com.dianping.cat.consumer.all.config; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ENTITY_ALL_CONFIG = "all-config"; + + public static final String ENTITY_NAME = "name"; + + public static final String ENTITY_NAMELIST = "nameList"; + + public static final String ENTITY_REPORT = "report"; + + public static final String ENTITY_REPORTS = "reports"; + + public static final String ENTITY_TYPE = "type"; + + public static final String ENTITY_TYPES = "types"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IEntity.java new file mode 100644 index 0000000000..fc34fca96d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.all.config; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IVisitor.java new file mode 100644 index 0000000000..5bd15447d5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/IVisitor.java @@ -0,0 +1,17 @@ +package com.dianping.cat.consumer.all.config; + +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public interface IVisitor { + + public void visitAllConfig(AllConfig allConfig); + + public void visitName(Name name); + + public void visitReport(Report report); + + public void visitType(Type type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/AllConfig.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/AllConfig.java new file mode 100644 index 0000000000..8a554d4daf --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/AllConfig.java @@ -0,0 +1,83 @@ +package com.dianping.cat.consumer.all.config.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.all.config.BaseEntity; +import com.dianping.cat.consumer.all.config.IVisitor; + +public class AllConfig extends BaseEntity { + private Map m_reports = new LinkedHashMap(); + + public AllConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAllConfig(this); + } + + public AllConfig addReport(Report report) { + m_reports.put(report.getId(), report); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AllConfig) { + AllConfig _o = (AllConfig) obj; + + if (!equals(getReports(), _o.getReports())) { + return false; + } + + + return true; + } + + return false; + } + + public Report findReport(String id) { + return m_reports.get(id); + } + + public Report findOrCreateReport(String id) { + Report report = m_reports.get(id); + + if (report == null) { + synchronized (m_reports) { + report = m_reports.get(id); + + if (report == null) { + report = new Report(id); + m_reports.put(id, report); + } + } + } + + return report; + } + + public Map getReports() { + return m_reports; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_reports == null ? 0 : m_reports.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(AllConfig other) { + } + + public Report removeReport(String id) { + return m_reports.remove(id); + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Name.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Name.java new file mode 100644 index 0000000000..a7d22b75d4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Name.java @@ -0,0 +1,58 @@ +package com.dianping.cat.consumer.all.config.entity; + +import com.dianping.cat.consumer.all.config.BaseEntity; +import com.dianping.cat.consumer.all.config.IVisitor; + +public class Name extends BaseEntity { + private String m_id; + + public Name() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitName(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Name) { + Name _o = (Name) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Name other) { + if (other.getId() != null) { + m_id = other.getId(); + } + } + + public Name setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Report.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Report.java new file mode 100644 index 0000000000..fb5fba7151 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Report.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.all.config.entity; + +import static com.dianping.cat.consumer.all.config.Constants.ATTR_ID; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_REPORT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.all.config.BaseEntity; +import com.dianping.cat.consumer.all.config.IVisitor; + +public class Report extends BaseEntity { + private String m_id; + + private Map m_types = new LinkedHashMap(); + + public Report() { + } + + public Report(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitReport(this); + } + + public Report addType(Type type) { + m_types.put(type.getId(), type); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Report) { + Report _o = (Report) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Type findType(String id) { + return m_types.get(id); + } + + public Type findOrCreateType(String id) { + Type type = m_types.get(id); + + if (type == null) { + synchronized (m_types) { + type = m_types.get(id); + + if (type == null) { + type = new Type(id); + m_types.put(id, type); + } + } + } + + return type; + } + + public String getId() { + return m_id; + } + + public Map getTypes() { + return m_types; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Report other) { + assertAttributeEquals(other, ENTITY_REPORT, ATTR_ID, m_id, other.getId()); + + } + + public Type removeType(String id) { + return m_types.remove(id); + } + + public Report setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Type.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Type.java new file mode 100644 index 0000000000..ea38397209 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/entity/Type.java @@ -0,0 +1,77 @@ +package com.dianping.cat.consumer.all.config.entity; + +import static com.dianping.cat.consumer.all.config.Constants.ATTR_ID; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_TYPE; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.consumer.all.config.BaseEntity; +import com.dianping.cat.consumer.all.config.IVisitor; + +public class Type extends BaseEntity { + private String m_id; + + private List m_nameList = new ArrayList(); + + public Type() { + } + + public Type(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitType(this); + } + + public Type addName(Name name) { + m_nameList.add(name); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Type) { + Type _o = (Type) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public List getNameList() { + return m_nameList; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Type other) { + assertAttributeEquals(other, ENTITY_TYPE, ATTR_ID, m_id, other.getId()); + + } + + public Type setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/BaseVisitor.java new file mode 100644 index 0000000000..ebcc5ccc49 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/BaseVisitor.java @@ -0,0 +1,34 @@ +package com.dianping.cat.consumer.all.config.transform; + +import com.dianping.cat.consumer.all.config.IVisitor; +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitAllConfig(AllConfig allConfig) { + for (Report report : allConfig.getReports().values()) { + visitReport(report); + } + } + + @Override + public void visitName(Name name) { + } + + @Override + public void visitReport(Report report) { + for (Type type : report.getTypes().values()) { + visitType(type); + } + } + + @Override + public void visitType(Type type) { + for (Name name : type.getNameList()) { + visitName(name); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultLinker.java new file mode 100644 index 0000000000..f2036cd6f7 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultLinker.java @@ -0,0 +1,62 @@ +package com.dianping.cat.consumer.all.config.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onName(final Type parent, final Name name) { + parent.addName(name); + return true; + } + + @Override + public boolean onReport(final AllConfig parent, final Report report) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addReport(report); + } + }); + } else { + parent.addReport(report); + } + + return true; + } + + @Override + public boolean onType(final Report parent, final Type type) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addType(type); + } + }); + } else { + parent.addType(type); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultMerger.java new file mode 100644 index 0000000000..09d26d999d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultMerger.java @@ -0,0 +1,135 @@ +package com.dianping.cat.consumer.all.config.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.all.config.IEntity; +import com.dianping.cat.consumer.all.config.IVisitor; +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private AllConfig m_allConfig; + + public DefaultMerger() { + } + + public DefaultMerger(AllConfig allConfig) { + m_allConfig = allConfig; + m_objs.push(allConfig); + } + + public AllConfig getAllConfig() { + return m_allConfig; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeAllConfig(AllConfig to, AllConfig from) { + to.mergeAttributes(from); + } + + protected void mergeName(Name to, Name from) { + to.mergeAttributes(from); + } + + protected void mergeReport(Report to, Report from) { + to.mergeAttributes(from); + } + + protected void mergeType(Type to, Type from) { + to.mergeAttributes(from); + } + + @Override + public void visitAllConfig(AllConfig from) { + AllConfig to = (AllConfig) m_objs.peek(); + + mergeAllConfig(to, from); + visitAllConfigChildren(to, from); + } + + protected void visitAllConfigChildren(AllConfig to, AllConfig from) { + for (Report source : from.getReports().values()) { + Report target = to.findReport(source.getId()); + + if (target == null) { + target = new Report(source.getId()); + to.addReport(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitName(Name from) { + Name to = (Name) m_objs.peek(); + + mergeName(to, from); + visitNameChildren(to, from); + } + + protected void visitNameChildren(Name to, Name from) { + } + + @Override + public void visitReport(Report from) { + Report to = (Report) m_objs.peek(); + + mergeReport(to, from); + visitReportChildren(to, from); + } + + protected void visitReportChildren(Report to, Report from) { + for (Type source : from.getTypes().values()) { + Type target = to.findType(source.getId()); + + if (target == null) { + target = new Type(source.getId()); + to.addType(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitType(Type from) { + Type to = (Type) m_objs.peek(); + + mergeType(to, from); + visitTypeChildren(to, from); + } + + protected void visitTypeChildren(Type to, Type from) { + for (Name source : from.getNameList()) { + Name target = null; + + if (target == null) { + target = new Name(); + to.addName(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..fec57e64de --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxMaker.java @@ -0,0 +1,75 @@ +package com.dianping.cat.consumer.all.config.transform; + +import static com.dianping.cat.consumer.all.config.Constants.ATTR_ID; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AllConfig buildAllConfig(Attributes attributes) { + AllConfig allConfig = new AllConfig(); + + return allConfig; + } + + @Override + public Name buildName(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Name name = new Name(); + + if (id != null) { + name.setId(id); + } + + return name; + } + + @Override + public Report buildReport(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Report report = new Report(id); + + return report; + } + + @Override + public Type buildType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Type type = new Type(id); + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..f4b2d70c14 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultSaxParser.java @@ -0,0 +1,273 @@ +package com.dianping.cat.consumer.all.config.transform; + +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_ALL_CONFIG; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_REPORT; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.all.config.IEntity; +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static AllConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(AllConfig.class, new InputSource(removeBOM(in))); + } + + public static AllConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(AllConfig.class, new InputSource(removeBOM(reader))); + } + + public static AllConfig parse(String xml) throws SAXException, IOException { + return parseEntity(AllConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAllConfig(AllConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_REPORT.equals(qName)) { + Report report = m_maker.buildReport(attributes); + + m_linker.onReport(parentObj, report); + m_objs.push(report); + } else { + throw new SAXException(String.format("Element(%s) is not expected under all-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForName(Name parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForReport(Report parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_linker.onType(parentObj, type); + m_objs.push(type); + } else { + throw new SAXException(String.format("Element(%s) is not expected under report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForType(Type parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_NAME.equals(qName)) { + Name name = m_maker.buildName(attributes); + + m_linker.onName(parentObj, name); + m_objs.push(name); + } else { + throw new SAXException(String.format("Element(%s) is not expected under type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_ALL_CONFIG.equals(qName)) { + AllConfig allConfig = m_maker.buildAllConfig(attributes); + + m_entity = allConfig; + m_objs.push(allConfig); + m_tags.push(qName); + } else if (ENTITY_REPORT.equals(qName)) { + Report report = m_maker.buildReport(attributes); + + m_entity = report; + m_objs.push(report); + m_tags.push(qName); + } else if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_entity = type; + m_objs.push(type); + m_tags.push(qName); + } else if (ENTITY_NAME.equals(qName)) { + Name name = m_maker.buildName(attributes); + + m_entity = name; + m_objs.push(name); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof AllConfig) { + parseForAllConfig((AllConfig) parent, tag, qName, attributes); + } else if (parent instanceof Report) { + parseForReport((Report) parent, tag, qName, attributes); + } else if (parent instanceof Type) { + parseForType((Type) parent, tag, qName, attributes); + } else if (parent instanceof Name) { + parseForName((Name) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..c267dea041 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/DefaultXmlBuilder.java @@ -0,0 +1,242 @@ +package com.dianping.cat.consumer.all.config.transform; + +import static com.dianping.cat.consumer.all.config.Constants.ATTR_ID; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_ALL_CONFIG; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_REPORT; +import static com.dianping.cat.consumer.all.config.Constants.ENTITY_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.all.config.IEntity; +import com.dianping.cat.consumer.all.config.IVisitor; +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitAllConfig(AllConfig allConfig) { + startTag(ENTITY_ALL_CONFIG, null); + + if (!allConfig.getReports().isEmpty()) { + for (Report report : allConfig.getReports().values()) { + report.accept(m_visitor); + } + } + + endTag(ENTITY_ALL_CONFIG); + } + + @Override + public void visitName(Name name) { + startTag(ENTITY_NAME, true, null, ATTR_ID, name.getId()); + } + + @Override + public void visitReport(Report report) { + startTag(ENTITY_REPORT, null, ATTR_ID, report.getId()); + + if (!report.getTypes().isEmpty()) { + for (Type type : report.getTypes().values()) { + type.accept(m_visitor); + } + } + + endTag(ENTITY_REPORT); + } + + @Override + public void visitType(Type type) { + startTag(ENTITY_TYPE, null, ATTR_ID, type.getId()); + + if (!type.getNameList().isEmpty()) { + for (Name name : type.getNameList()) { + name.accept(m_visitor); + } + } + + endTag(ENTITY_TYPE); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/ILinker.java new file mode 100644 index 0000000000..73f49b5aa5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/ILinker.java @@ -0,0 +1,15 @@ +package com.dianping.cat.consumer.all.config.transform; + +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public interface ILinker { + + public boolean onName(Type parent, Name name); + + public boolean onReport(AllConfig parent, Report report); + + public boolean onType(Report parent, Type type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IMaker.java new file mode 100644 index 0000000000..0e423f378a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IMaker.java @@ -0,0 +1,17 @@ +package com.dianping.cat.consumer.all.config.transform; + +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public interface IMaker { + + public AllConfig buildAllConfig(T node); + + public Name buildName(T node); + + public Report buildReport(T node); + + public Type buildType(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IParser.java new file mode 100644 index 0000000000..5c4f43fc2f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/all/config/transform/IParser.java @@ -0,0 +1,16 @@ +package com.dianping.cat.consumer.all.config.transform; + +import com.dianping.cat.consumer.all.config.entity.AllConfig; +import com.dianping.cat.consumer.all.config.entity.Name; +import com.dianping.cat.consumer.all.config.entity.Report; +import com.dianping.cat.consumer.all.config.entity.Type; + +public interface IParser { + public AllConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForName(IMaker maker, ILinker linker, Name parent, T node); + + public void parseForReport(IMaker maker, ILinker linker, Report parent, T node); + + public void parseForType(IMaker maker, ILinker linker, Type parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/build/ComponentsConfigurator.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/build/ComponentsConfigurator.java deleted file mode 100644 index d85ccbaf98..0000000000 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/build/ComponentsConfigurator.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.build; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.unidal.initialization.Module; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.analysis.MessageAnalyzer; -import com.dianping.cat.config.AtomicMessageConfigManager; -import com.dianping.cat.config.server.ServerConfigManager; -import com.dianping.cat.config.transaction.TpValueStatisticConfigManager; -import com.dianping.cat.consumer.CatConsumerModule; -import com.dianping.cat.consumer.DatabaseParser; -import com.dianping.cat.consumer.business.BusinessAnalyzer; -import com.dianping.cat.consumer.business.BusinessDelegate; -import com.dianping.cat.consumer.config.AllReportConfigManager; -import com.dianping.cat.consumer.cross.CrossAnalyzer; -import com.dianping.cat.consumer.cross.CrossDelegate; -import com.dianping.cat.consumer.cross.IpConvertManager; -import com.dianping.cat.consumer.dependency.DependencyAnalyzer; -import com.dianping.cat.consumer.dependency.DependencyDelegate; -import com.dianping.cat.consumer.dump.DumpAnalyzer; -import com.dianping.cat.consumer.dump.LocalMessageBucketManager; -import com.dianping.cat.consumer.event.EventAnalyzer; -import com.dianping.cat.consumer.event.EventDelegate; -import com.dianping.cat.consumer.heartbeat.HeartbeatAnalyzer; -import com.dianping.cat.consumer.heartbeat.HeartbeatDelegate; -import com.dianping.cat.consumer.matrix.MatrixAnalyzer; -import com.dianping.cat.consumer.matrix.MatrixDelegate; -import com.dianping.cat.consumer.problem.DefaultProblemHandler; -import com.dianping.cat.consumer.problem.LongExecutionProblemHandler; -import com.dianping.cat.consumer.problem.ProblemAnalyzer; -import com.dianping.cat.consumer.problem.ProblemDelegate; -import com.dianping.cat.consumer.problem.ProblemHandler; -import com.dianping.cat.consumer.state.StateAnalyzer; -import com.dianping.cat.consumer.state.StateDelegate; -import com.dianping.cat.consumer.storage.StorageAnalyzer; -import com.dianping.cat.consumer.storage.StorageDelegate; -import com.dianping.cat.consumer.storage.StorageReportUpdater; -import com.dianping.cat.consumer.storage.builder.StorageBuilderManager; -import com.dianping.cat.consumer.storage.builder.StorageCacheBuilder; -import com.dianping.cat.consumer.storage.builder.StorageRPCBuilder; -import com.dianping.cat.consumer.storage.builder.StorageSQLBuilder; -import com.dianping.cat.consumer.top.TopAnalyzer; -import com.dianping.cat.consumer.top.TopDelegate; -import com.dianping.cat.consumer.transaction.TransactionAnalyzer; -import com.dianping.cat.consumer.transaction.TransactionDelegate; -import com.dianping.cat.core.dal.HourlyReportContentDao; -import com.dianping.cat.core.dal.HourlyReportDao; -import com.dianping.cat.message.PathBuilder; -import com.dianping.cat.message.storage.MessageBucketManager; -import com.dianping.cat.report.DefaultReportManager; -import com.dianping.cat.report.DomainValidator; -import com.dianping.cat.report.ReportBucketManager; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; -import com.dianping.cat.service.ProjectService; -import com.dianping.cat.statistic.ServerStatisticManager; - -public class ComponentsConfigurator extends AbstractResourceConfigurator { - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new ComponentsConfigurator()); - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - - all.addAll(defineTransactionComponents()); - all.addAll(defineEventComponents()); - all.addAll(defineProblemComponents()); - all.addAll(defineHeartbeatComponents()); - all.addAll(defineTopComponents()); - all.addAll(defineDumpComponents()); - all.addAll(defineStateComponents()); - all.addAll(defineCrossComponents()); - all.addAll(defineMatrixComponents()); - all.addAll(defineDependencyComponents()); - all.addAll(defineStorageComponents()); - all.addAll(defineBusinessComponents()); - - all.add(A(AtomicMessageConfigManager.class)); - all.add(A(ServerConfigManager.class)); - all.add(A(TpValueStatisticConfigManager.class)); - all.add(A(AllReportConfigManager.class)); - all.add(C(Module.class, CatConsumerModule.ID, CatConsumerModule.class)); - - return all; - } - - private Collection defineCrossComponents() { - final List all = new ArrayList(); - final String ID = CrossAnalyzer.ID; - - all.add(A(CrossAnalyzer.class)); - all.add(A(CrossDelegate.class)); - - all.add(C(IpConvertManager.class)); - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineDependencyComponents() { - final List all = new ArrayList(); - final String ID = DependencyAnalyzer.ID; - - all.add(A(DependencyAnalyzer.class)); - all.add(A(DependencyDelegate.class)); - - all.add(C(DatabaseParser.class)); - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineDumpComponents() { - final List all = new ArrayList(); - all.add(A(DumpAnalyzer.class)); - - all.add(C(MessageBucketManager.class, LocalMessageBucketManager.ID, LocalMessageBucketManager.class) // - .req(ServerConfigManager.class, PathBuilder.class, ServerStatisticManager.class)); - - return all; - } - - private Collection defineEventComponents() { - final List all = new ArrayList(); - final String ID = EventAnalyzer.ID; - - all.add(A(EventAnalyzer.class)); - all.add(A(EventDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineHeartbeatComponents() { - final List all = new ArrayList(); - final String ID = HeartbeatAnalyzer.ID; - - all.add(A(HeartbeatAnalyzer.class)); - all.add(A(HeartbeatDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineMatrixComponents() { - final List all = new ArrayList(); - final String ID = MatrixAnalyzer.ID; - - all.add(A(MatrixAnalyzer.class)); - all.add(A(MatrixDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineBusinessComponents() { - final List all = new ArrayList(); - final String ID = BusinessAnalyzer.ID; - - all.add(A(BusinessAnalyzer.class)); - all.add(A(BusinessDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - return all; - } - - private Collection defineProblemComponents() { - final List all = new ArrayList(); - final String ID = ProblemAnalyzer.ID; - - all.add(C(ProblemHandler.class, DefaultProblemHandler.ID, DefaultProblemHandler.class)// - .config(E("errorType").value("Error,RuntimeException,Exception"))// - .req(ServerConfigManager.class)); - - all.add(C(ProblemHandler.class, LongExecutionProblemHandler.ID, LongExecutionProblemHandler.class) // - .req(ServerConfigManager.class)); - - all.add(C(MessageAnalyzer.class, ID, ProblemAnalyzer.class).is(PER_LOOKUP) // - .req(ReportManager.class, ID).req(ServerConfigManager.class).req(ProblemHandler.class, // - new String[] { DefaultProblemHandler.ID, LongExecutionProblemHandler.ID }, "m_handlers")); - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - all.add(A(ProblemDelegate.class)); - - return all; - } - - private Collection defineStateComponents() { - final List all = new ArrayList(); - final String ID = StateAnalyzer.ID; - - all.add(A(StateAnalyzer.class)); - all.add(A(StateDelegate.class)); - - all.add(A(ProjectService.class)); - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineTopComponents() { - final List all = new ArrayList(); - final String ID = TopAnalyzer.ID; - - all.add(A(TopAnalyzer.class).config(E("errorType").value("Error,RuntimeException,Exception"))); - all.add(A(TopDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineTransactionComponents() { - final List all = new ArrayList(); - final String ID = TransactionAnalyzer.ID; - - all.add(A(TransactionAnalyzer.class)); - all.add(A(TransactionDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } - - private Collection defineStorageComponents() { - final List all = new ArrayList(); - final String ID = StorageAnalyzer.ID; - - all.add(A(StorageReportUpdater.class)); - all.add(A(StorageBuilderManager.class)); - all.add(A(StorageSQLBuilder.class)); - all.add(A(StorageCacheBuilder.class)); - all.add(A(StorageRPCBuilder.class)); - - all.add(A(StorageAnalyzer.class)); - all.add(A(StorageDelegate.class)); - - all.add(C(ReportManager.class, ID, DefaultReportManager.class).is(PER_LOOKUP) // - .req(ReportDelegate.class, ID) // - .req(ReportBucketManager.class, HourlyReportDao.class, HourlyReportContentDao.class, DomainValidator.class) // - .config(E("name").value(ID))); - - return all; - } -} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessAnalyzer.java index 0668d20a58..3c8b28baf5 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessAnalyzer.java @@ -18,17 +18,11 @@ */ package com.dianping.cat.consumer.business; -import java.util.List; - -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.analysis.AbstractMessageAnalyzer; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.config.business.BusinessConfigManager; import com.dianping.cat.config.business.ConfigItem; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.business.model.entity.BusinessItem; import com.dianping.cat.consumer.business.model.entity.BusinessReport; import com.dianping.cat.consumer.business.model.entity.Segment; @@ -37,41 +31,44 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; +import jakarta.annotation.Resource; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = BusinessAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class BusinessAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +import java.util.List; + +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + BusinessAnalyzer.ID) +@Scope("prototype") +public class BusinessAnalyzer extends AbstractMessageAnalyzer { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(BusinessAnalyzer.class); public static final String ID = "business"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = BusinessAnalyzer.ID + "ReportManager") + private ReportManager reportManager; - @Inject - private BusinessConfigManager m_configManager; + @Resource(name = "businessConfigManager") + private BusinessConfigManager businessConfigManager; @Override public void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public BusinessReport getReport(String domain) { long period = getStartTime(); - return m_reportManager.getHourlyReport(period, domain, false); + return reportManager.getHourlyReport(period, domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return reportManager; } @Override @@ -81,7 +78,7 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } ConfigItem parseValue(Metric metric) { @@ -110,7 +107,7 @@ ConfigItem parseValue(Metric metric) { @Override protected void process(MessageTree tree) { String domain = tree.getDomain(); - BusinessReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + BusinessReport report = reportManager.getHourlyReport(getStartTime(), domain, true); List metrics = tree.getMetrics(); for (Metric metric : metrics) { @@ -136,12 +133,17 @@ private void processMetric(BusinessReport report, Metric metric, String domain) config.setTitle(name); - boolean result = m_configManager.insertBusinessConfigIfNotExist(domain, name, config); + boolean result = businessConfigManager.insertBusinessConfigIfNotExist(domain, name, config); if (!result) { - m_logger.error( - String.format("error when insert business config info, domain %s, metricName %s", domain, name)); + LOGGER.error("error when insert business config info, domain {}, metricName {}", domain, name); } } } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessDelegate.java index 06b730e9ef..9332b9ad9a 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/BusinessDelegate.java @@ -21,9 +21,6 @@ import java.util.Date; import java.util.Map; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.consumer.business.model.entity.BusinessReport; import com.dianping.cat.consumer.business.model.transform.DefaultNativeBuilder; import com.dianping.cat.consumer.business.model.transform.DefaultNativeParser; @@ -32,10 +29,8 @@ import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -@Named(type = ReportDelegate.class, value = BusinessAnalyzer.ID) public class BusinessDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; @Override @@ -94,4 +89,8 @@ public boolean createHourlyTask(BusinessReport report) { return m_taskManager.createTask(report.getStartTime(), report.getDomain(), BusinessAnalyzer.ID, TaskProlicy.DAILY); } + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/BaseEntity.java new file mode 100644 index 0000000000..24ee9b5b06 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.business.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.business.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/Constants.java new file mode 100644 index 0000000000..7a335a0b2f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/Constants.java @@ -0,0 +1,30 @@ +package com.dianping.cat.consumer.business.model; + +public class Constants { + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_SUM = "sum"; + + public static final String ATTR_TYPE = "type"; + + public static final String ENTITY_BUSINESS_ITEM = "business-item"; + + public static final String ENTITY_BUSINESS_ITEMS = "business-items"; + + public static final String ENTITY_BUSINESS_REPORT = "business-report"; + + public static final String ENTITY_SEGMENT = "segment"; + + public static final String ENTITY_SEGMENTS = "segments"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IEntity.java new file mode 100644 index 0000000000..57ae3e2c92 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.business.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IVisitor.java new file mode 100644 index 0000000000..91b9863510 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.consumer.business.model; + +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public interface IVisitor { + + public void visitBusinessItem(BusinessItem businessItem); + + public void visitBusinessReport(BusinessReport businessReport); + + public void visitSegment(Segment segment); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessItem.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessItem.java new file mode 100644 index 0000000000..27abe619ce --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessItem.java @@ -0,0 +1,116 @@ +package com.dianping.cat.consumer.business.model.entity; + +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_ITEM; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.business.model.BaseEntity; +import com.dianping.cat.consumer.business.model.IVisitor; + +public class BusinessItem extends BaseEntity { + private String m_id; + + private String m_type; + + private Map m_segments = new LinkedHashMap(); + + public BusinessItem() { + } + + public BusinessItem(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitBusinessItem(this); + } + + public BusinessItem addSegment(Segment segment) { + m_segments.put(segment.getId(), segment); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BusinessItem) { + BusinessItem _o = (BusinessItem) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Segment findSegment(Integer id) { + return m_segments.get(id); + } + + public Segment findOrCreateSegment(Integer id) { + Segment segment = m_segments.get(id); + + if (segment == null) { + synchronized (m_segments) { + segment = m_segments.get(id); + + if (segment == null) { + segment = new Segment(id); + m_segments.put(id, segment); + } + } + } + + return segment; + } + + public String getId() { + return m_id; + } + + public Map getSegments() { + return m_segments; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(BusinessItem other) { + assertAttributeEquals(other, ENTITY_BUSINESS_ITEM, ATTR_ID, m_id, other.getId()); + + if (other.getType() != null) { + m_type = other.getType(); + } + } + + public Segment removeSegment(Integer id) { + return m_segments.remove(id); + } + + public BusinessItem setId(String id) { + m_id = id; + return this; + } + + public BusinessItem setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessReport.java new file mode 100644 index 0000000000..e860700f91 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/BusinessReport.java @@ -0,0 +1,131 @@ +package com.dianping.cat.consumer.business.model.entity; + +import static com.dianping.cat.consumer.business.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_REPORT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.business.model.BaseEntity; +import com.dianping.cat.consumer.business.model.IVisitor; + +public class BusinessReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_businessItems = new LinkedHashMap(); + + public BusinessReport() { + } + + public BusinessReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitBusinessReport(this); + } + + public BusinessReport addBusinessItem(BusinessItem businessItem) { + m_businessItems.put(businessItem.getId(), businessItem); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BusinessReport) { + BusinessReport _o = (BusinessReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public BusinessItem findBusinessItem(String id) { + return m_businessItems.get(id); + } + + public BusinessItem findOrCreateBusinessItem(String id) { + BusinessItem businessItem = m_businessItems.get(id); + + if (businessItem == null) { + synchronized (m_businessItems) { + businessItem = m_businessItems.get(id); + + if (businessItem == null) { + businessItem = new BusinessItem(id); + m_businessItems.put(id, businessItem); + } + } + } + + return businessItem; + } + + public Map getBusinessItems() { + return m_businessItems; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(BusinessReport other) { + assertAttributeEquals(other, ENTITY_BUSINESS_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public BusinessItem removeBusinessItem(String id) { + return m_businessItems.remove(id); + } + + public BusinessReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public BusinessReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public BusinessReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/Segment.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/Segment.java new file mode 100644 index 0000000000..f357d1bcf3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/entity/Segment.java @@ -0,0 +1,121 @@ +package com.dianping.cat.consumer.business.model.entity; + +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_SEGMENT; + +import com.dianping.cat.consumer.business.model.BaseEntity; +import com.dianping.cat.consumer.business.model.IVisitor; + +public class Segment extends BaseEntity { + private Integer m_id; + + private int m_count; + + private double m_sum; + + private double m_avg; + + public Segment() { + } + + public Segment(Integer id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSegment(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Segment) { + Segment _o = (Segment) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public double getAvg() { + return m_avg; + } + + public int getCount() { + return m_count; + } + + public Integer getId() { + return m_id; + } + + public double getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Segment incCount() { + m_count++; + return this; + } + + public Segment incCount(int count) { + m_count += count; + return this; + } + + public Segment incSum() { + m_sum++; + return this; + } + + public Segment incSum(double sum) { + m_sum += sum; + return this; + } + + @Override + public void mergeAttributes(Segment other) { + assertAttributeEquals(other, ENTITY_SEGMENT, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + } + + public Segment setAvg(double avg) { + m_avg = avg; + return this; + } + + public Segment setCount(int count) { + m_count = count; + return this; + } + + public Segment setId(Integer id) { + m_id = id; + return this; + } + + public Segment setSum(double sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..05f15bff72 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/BaseVisitor.java @@ -0,0 +1,26 @@ +package com.dianping.cat.consumer.business.model.transform; + +import com.dianping.cat.consumer.business.model.IVisitor; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitBusinessItem(BusinessItem businessItem) { + for (Segment segment : businessItem.getSegments().values()) { + visitSegment(segment); + } + } + + @Override + public void visitBusinessReport(BusinessReport businessReport) { + for (BusinessItem businessItem : businessReport.getBusinessItems().values()) { + visitBusinessItem(businessItem); + } + } + + @Override + public void visitSegment(Segment segment) { + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..282b81946d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultLinker.java @@ -0,0 +1,55 @@ +package com.dianping.cat.consumer.business.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onBusinessItem(final BusinessReport parent, final BusinessItem businessItem) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addBusinessItem(businessItem); + } + }); + } else { + parent.addBusinessItem(businessItem); + } + + return true; + } + + @Override + public boolean onSegment(final BusinessItem parent, final Segment segment) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSegment(segment); + } + }); + } else { + parent.addSegment(segment); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..0d0ac2560f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultMerger.java @@ -0,0 +1,107 @@ +package com.dianping.cat.consumer.business.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.business.model.IEntity; +import com.dianping.cat.consumer.business.model.IVisitor; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private BusinessReport m_businessReport; + + public DefaultMerger() { + } + + public DefaultMerger(BusinessReport businessReport) { + m_businessReport = businessReport; + m_objs.push(businessReport); + } + + public BusinessReport getBusinessReport() { + return m_businessReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeBusinessItem(BusinessItem to, BusinessItem from) { + to.mergeAttributes(from); + } + + protected void mergeBusinessReport(BusinessReport to, BusinessReport from) { + to.mergeAttributes(from); + } + + protected void mergeSegment(Segment to, Segment from) { + to.mergeAttributes(from); + } + + @Override + public void visitBusinessItem(BusinessItem from) { + BusinessItem to = (BusinessItem) m_objs.peek(); + + mergeBusinessItem(to, from); + visitBusinessItemChildren(to, from); + } + + protected void visitBusinessItemChildren(BusinessItem to, BusinessItem from) { + for (Segment source : from.getSegments().values()) { + Segment target = to.findSegment(source.getId()); + + if (target == null) { + target = new Segment(source.getId()); + to.addSegment(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitBusinessReport(BusinessReport from) { + BusinessReport to = (BusinessReport) m_objs.peek(); + + mergeBusinessReport(to, from); + visitBusinessReportChildren(to, from); + } + + protected void visitBusinessReportChildren(BusinessReport to, BusinessReport from) { + for (BusinessItem source : from.getBusinessItems().values()) { + BusinessItem target = to.findBusinessItem(source.getId()); + + if (target == null) { + target = new BusinessItem(source.getId()); + to.addBusinessItem(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitSegment(Segment from) { + Segment to = (Segment) m_objs.peek(); + + mergeSegment(to, from); + visitSegmentChildren(to, from); + } + + protected void visitSegmentChildren(Segment to, Segment from) { + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..46a64e4ba7 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,164 @@ +package com.dianping.cat.consumer.business.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.business.model.IVisitor; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(BusinessReport businessReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(businessReport, out); + return out.toByteArray(); + } + + public static void build(BusinessReport businessReport, OutputStream out) { + businessReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitBusinessItem(BusinessItem businessItem) { + if (businessItem.getId() != null) { + writeTag(1, 1); + writeString(businessItem.getId()); + } + + if (businessItem.getType() != null) { + writeTag(2, 1); + writeString(businessItem.getType()); + } + + if (!businessItem.getSegments().isEmpty()) { + writeTag(33, 2); + writeInt(businessItem.getSegments().size()); + + for (Segment segment : businessItem.getSegments().values()) { + segment.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitBusinessReport(BusinessReport businessReport) { + writeTag(63, 0); + + if (businessReport.getDomain() != null) { + writeTag(1, 1); + writeString(businessReport.getDomain()); + } + + if (businessReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(businessReport.getStartTime()); + } + + if (businessReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(businessReport.getEndTime()); + } + + if (!businessReport.getBusinessItems().isEmpty()) { + writeTag(33, 2); + writeInt(businessReport.getBusinessItems().size()); + + for (BusinessItem businessItem : businessReport.getBusinessItems().values()) { + businessItem.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitSegment(Segment segment) { + if (segment.getId() != null) { + writeTag(1, 1); + writeInt(segment.getId()); + } + + writeTag(2, 0); + writeInt(segment.getCount()); + + writeTag(3, 0); + writeDouble(segment.getSum()); + + writeTag(4, 0); + writeDouble(segment.getAvg()); + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..399046a516 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultNativeParser.java @@ -0,0 +1,203 @@ +package com.dianping.cat.consumer.business.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.business.model.IVisitor; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static BusinessReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static BusinessReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + BusinessReport businessReport = new BusinessReport(); + + try { + businessReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return businessReport; + } + + @Override + public void visitBusinessItem(BusinessItem businessItem) { + byte tag; + + while ((tag = readTag()) != -1) { + visitBusinessItemChildren(businessItem, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitBusinessItemChildren(BusinessItem businessItem, int _field, int _type) { + switch (_field) { + case 1: + businessItem.setId(readString()); + break; + case 2: + businessItem.setType(readString()); + break; + case 33: + if (_type == 1) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(businessItem, segment); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(businessItem, segment); + } + } + break; + } + } + + @Override + public void visitBusinessReport(BusinessReport businessReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitBusinessReportChildren(businessReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitBusinessReportChildren(BusinessReport businessReport, int _field, int _type) { + switch (_field) { + case 1: + businessReport.setDomain(readString()); + break; + case 2: + businessReport.setStartTime(readDate()); + break; + case 3: + businessReport.setEndTime(readDate()); + break; + case 33: + if (_type == 1) { + BusinessItem businessItem = new BusinessItem(); + + visitBusinessItem(businessItem); + m_linker.onBusinessItem(businessReport, businessItem); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + BusinessItem businessItem = new BusinessItem(); + + visitBusinessItem(businessItem); + m_linker.onBusinessItem(businessReport, businessItem); + } + } + break; + } + } + + @Override + public void visitSegment(Segment segment) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSegmentChildren(segment, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSegmentChildren(Segment segment, int _field, int _type) { + switch (_field) { + case 1: + segment.setId(readInt()); + break; + case 2: + segment.setCount(readInt()); + break; + case 3: + segment.setSum(readDouble()); + break; + case 4: + segment.setAvg(readDouble()); + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..2b219631ce --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxMaker.java @@ -0,0 +1,112 @@ +package com.dianping.cat.consumer.business.model.transform; + +import static com.dianping.cat.consumer.business.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_TYPE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultSaxMaker implements IMaker { + + @Override + public BusinessItem buildBusinessItem(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String type = attributes.getValue(ATTR_TYPE); + BusinessItem businessItem = new BusinessItem(id); + + if (type != null) { + businessItem.setType(type); + } + + return businessItem; + } + + @Override + public BusinessReport buildBusinessReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + BusinessReport businessReport = new BusinessReport(domain); + + if (startTime != null) { + businessReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + businessReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return businessReport; + } + + @Override + public Segment buildSegment(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + Segment segment = new Segment(id == null ? null : convert(Integer.class, id, null)); + + if (count != null) { + segment.setCount(convert(Integer.class, count, 0)); + } + + if (sum != null) { + segment.setSum(convert(Double.class, sum, 0.0)); + } + + if (avg != null) { + segment.setAvg(convert(Double.class, avg, 0.0)); + } + + return segment; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..ffceee61e0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultSaxParser.java @@ -0,0 +1,258 @@ +package com.dianping.cat.consumer.business.model.transform; + +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_ITEM; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_REPORT; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_SEGMENT; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.business.model.IEntity; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static BusinessReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(BusinessReport.class, new InputSource(removeBOM(in))); + } + + public static BusinessReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(BusinessReport.class, new InputSource(removeBOM(reader))); + } + + public static BusinessReport parse(String xml) throws SAXException, IOException { + return parseEntity(BusinessReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForBusinessItem(BusinessItem parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_linker.onSegment(parentObj, segment); + m_objs.push(segment); + } else { + throw new SAXException(String.format("Element(%s) is not expected under business-item!", qName)); + } + + m_tags.push(qName); + } + + private void parseForBusinessReport(BusinessReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_BUSINESS_ITEM.equals(qName)) { + BusinessItem businessItem = m_maker.buildBusinessItem(attributes); + + m_linker.onBusinessItem(parentObj, businessItem); + m_objs.push(businessItem); + } else { + throw new SAXException(String.format("Element(%s) is not expected under business-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSegment(Segment parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_BUSINESS_REPORT.equals(qName)) { + BusinessReport businessReport = m_maker.buildBusinessReport(attributes); + + m_entity = businessReport; + m_objs.push(businessReport); + m_tags.push(qName); + } else if (ENTITY_BUSINESS_ITEM.equals(qName)) { + BusinessItem businessItem = m_maker.buildBusinessItem(attributes); + + m_entity = businessItem; + m_objs.push(businessItem); + m_tags.push(qName); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_entity = segment; + m_objs.push(segment); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof BusinessReport) { + parseForBusinessReport((BusinessReport) parent, tag, qName, attributes); + } else if (parent instanceof BusinessItem) { + parseForBusinessItem((BusinessItem) parent, tag, qName, attributes); + } else if (parent instanceof Segment) { + parseForSegment((Segment) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..871d0b40cd --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,242 @@ +package com.dianping.cat.consumer.business.model.transform; + +import static com.dianping.cat.consumer.business.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.business.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_ITEM; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_BUSINESS_REPORT; +import static com.dianping.cat.consumer.business.model.Constants.ENTITY_SEGMENT; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.business.model.IEntity; +import com.dianping.cat.consumer.business.model.IVisitor; +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + @Override + public void visitBusinessItem(BusinessItem businessItem) { + startTag(ENTITY_BUSINESS_ITEM, null, ATTR_ID, businessItem.getId(), ATTR_TYPE, businessItem.getType()); + + if (!businessItem.getSegments().isEmpty()) { + for (Segment segment : businessItem.getSegments().values()) { + segment.accept(m_visitor); + } + } + + endTag(ENTITY_BUSINESS_ITEM); + } + + @Override + public void visitBusinessReport(BusinessReport businessReport) { + startTag(ENTITY_BUSINESS_REPORT, null, ATTR_DOMAIN, businessReport.getDomain(), ATTR_STARTTIME, toString(businessReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(businessReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!businessReport.getBusinessItems().isEmpty()) { + for (BusinessItem businessItem : businessReport.getBusinessItems().values()) { + businessItem.accept(m_visitor); + } + } + + endTag(ENTITY_BUSINESS_REPORT); + } + + @Override + public void visitSegment(Segment segment) { + startTag(ENTITY_SEGMENT, true, null, ATTR_ID, segment.getId(), ATTR_COUNT, segment.getCount(), ATTR_SUM, segment.getSum(), ATTR_AVG, segment.getAvg()); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/ILinker.java new file mode 100644 index 0000000000..f43bd4aef9 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.consumer.business.model.transform; + +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public interface ILinker { + + public boolean onBusinessItem(BusinessReport parent, BusinessItem businessItem); + + public boolean onSegment(BusinessItem parent, Segment segment); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IMaker.java new file mode 100644 index 0000000000..7e9f6c9c4d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.consumer.business.model.transform; + +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public interface IMaker { + + public BusinessItem buildBusinessItem(T node); + + public BusinessReport buildBusinessReport(T node); + + public Segment buildSegment(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IParser.java new file mode 100644 index 0000000000..a2316d4067 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/business/model/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.consumer.business.model.transform; + +import com.dianping.cat.consumer.business.model.entity.BusinessItem; +import com.dianping.cat.consumer.business.model.entity.BusinessReport; +import com.dianping.cat.consumer.business.model.entity.Segment; + +public interface IParser { + public BusinessReport parse(IMaker maker, ILinker linker, T node); + + public void parseForBusinessItem(IMaker maker, ILinker linker, BusinessItem parent, T node); + + public void parseForSegment(IMaker maker, ILinker linker, Segment parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/config/AllReportConfigManager.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/config/AllReportConfigManager.java index 45a4b8d400..dc2ed09566 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/config/AllReportConfigManager.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/config/AllReportConfigManager.java @@ -23,14 +23,8 @@ 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.unidal.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; import org.xml.sax.SAXException; import com.dianping.cat.Cat; @@ -41,49 +35,51 @@ import com.dianping.cat.consumer.all.config.entity.Type; import com.dianping.cat.consumer.all.config.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class AllReportConfigManager implements Initializable, LogEnabled { +public class AllReportConfigManager { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AllReportConfigManager.class); private static final String CONFIG_NAME = "all-report-config"; - @Inject - private ConfigDao m_configDao; + private ConfigRepository m_configDao; - @Inject private ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private volatile AllConfig m_config; - private Logger m_logger; - private long m_modifyTime; - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } + private volatile boolean m_initialized; public AllConfig getConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); m_modifyTime = config.getModifyDate().getTime(); - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -119,9 +115,12 @@ public String getName() { return CONFIG_NAME; } }); + m_initialized = true; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); boolean result = storeConfig(); @@ -129,13 +128,13 @@ public boolean insert(String xml) { return result; } catch (Exception e) { Cat.logError(e); - m_logger.error(e.getMessage(), e); + LOGGER.error("Unable to insert all report config.", e); return false; } } - private void refreshConfig() throws DalException, SAXException, IOException { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + private void refreshConfig() throws SAXException, IOException { + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -158,7 +157,7 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); } catch (Exception e) { Cat.logError(e); return false; @@ -168,6 +167,8 @@ private boolean storeConfig() { } public boolean validate(String reportName, String type) { + ensureInitialized(); + Report report = m_config.getReports().get(reportName); if (report != null) { @@ -180,6 +181,8 @@ public boolean validate(String reportName, String type) { } public boolean validate(String reportName, String type, String name) { + ensureInitialized(); + Report report = m_config.getReports().get(reportName); if (report != null) { @@ -201,4 +204,12 @@ public boolean validate(String reportName, String type, String name) { return false; } -} \ No newline at end of file + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossAnalyzer.java index 86cbc85a49..a8b7aa789e 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossAnalyzer.java @@ -19,7 +19,7 @@ package com.dianping.cat.consumer.cross; import com.dianping.cat.analysis.AbstractMessageAnalyzer; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.cross.model.entity.*; import com.dianping.cat.message.Event; @@ -28,25 +28,28 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; -import org.unidal.lookup.util.StringUtils; +import jakarta.annotation.Resource; +import org.apache.commons.lang.StringUtils; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; import java.util.List; -@Named(type = MessageAnalyzer.class, value = CrossAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class CrossAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + CrossAnalyzer.ID) +@Scope("prototype") +public class CrossAnalyzer extends AbstractMessageAnalyzer { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(CrossAnalyzer.class); + public static final String ID = "cross"; public static final String DEFAULT = "unknown"; - @Inject(ID) - protected ReportManager m_reportManager; + @Resource(name = "crossReportManager") + protected ReportManager reportManager; - @Inject - protected IpConvertManager m_ipConvertManager; + @Resource(name = "ipConvertManager") + protected IpConvertManager ipConvertManager; private int m_discardLogs = 0; @@ -82,31 +85,22 @@ public CrossInfo convertCrossInfo(String client, CrossInfo crossInfo) { @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); - m_logger.info("discard server logview count " + m_discardLogs + ", errorAppName " + m_errorAppName); + LOGGER.info("discard server logview count {}, errorAppName {}", m_discardLogs, m_errorAppName); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public CrossReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, false); + return reportManager.getHourlyReport(getStartTime(), domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; - } - - public void setReportManager(ReportManager reportManager) { - m_reportManager = reportManager; + return reportManager; } @Override @@ -120,7 +114,7 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } public CrossInfo parseCrossTransaction(Transaction t, MessageTree tree) { @@ -188,7 +182,7 @@ private CrossInfo parsePigeonServerTransaction(Transaction t, MessageTree tree) @Override public void process(MessageTree tree) { String domain = tree.getDomain(); - CrossReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + CrossReport report = reportManager.getHourlyReport(getStartTime(), domain, true); report.addIp(tree.getIpAddress()); @@ -212,7 +206,7 @@ private void processTransaction(CrossReport report, MessageTree tree, Transactio CrossInfo serverCrossInfo = convertCrossInfo(tree.getDomain(), crossInfo); if (serverCrossInfo != null) { - CrossReport serverReport = m_reportManager.getHourlyReport(getStartTime(), targetDomain, true); + CrossReport serverReport = reportManager.getHourlyReport(getStartTime(), targetDomain, true); updateCrossReport(serverReport, t, serverCrossInfo); } @@ -223,9 +217,14 @@ private void processTransaction(CrossReport report, MessageTree tree, Transactio } public void setIpConvertManager(IpConvertManager ipConvertManager) { - m_ipConvertManager = ipConvertManager; + this.ipConvertManager = ipConvertManager; + } + + public void setReportManager(ReportManager reportManager) { + this.reportManager = reportManager; } + @Resource(name = "serverConfigManager") public void setServerConfigManager(ServerConfigManager serverConfigManager) { m_serverConfigManager = serverConfigManager; } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossDelegate.java index bd30c20e0f..bce07f5f50 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/CrossDelegate.java @@ -26,19 +26,14 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = CrossAnalyzer.ID) public class CrossDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_serverFilterConfigManager; @Override @@ -102,4 +97,12 @@ public CrossReport parseBinary(byte[] bytes) { public CrossReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setServerFilterConfigManager(ServerFilterConfigManager serverFilterConfigManager) { + m_serverFilterConfigManager = serverFilterConfigManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/BaseEntity.java new file mode 100644 index 0000000000..2ea5ba9bc0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.cross.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.cross.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/Constants.java new file mode 100644 index 0000000000..d9477e68a1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/Constants.java @@ -0,0 +1,54 @@ +package com.dianping.cat.consumer.cross.model; + +public class Constants { + + public static final String ATTR_APP = "app"; + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_FAILCOUNT = "failCount"; + + public static final String ATTR_FAILPERCENT = "failPercent"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_ROLE = "role"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_SUM = "sum"; + + public static final String ATTR_TOTALCOUNT = "totalCount"; + + public static final String ATTR_TPS = "tps"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ENTITY_CROSS_REPORT = "cross-report"; + + public static final String ENTITY_LOCAL = "local"; + + public static final String ENTITY_LOCALS = "locals"; + + public static final String ENTITY_NAME = "name"; + + public static final String ENTITY_NAMES = "names"; + + public static final String ENTITY_REMOTE = "remote"; + + public static final String ENTITY_REMOTES = "remotes"; + + public static final String ENTITY_TYPE = "type"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IEntity.java new file mode 100644 index 0000000000..2579607e39 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.cross.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IVisitor.java new file mode 100644 index 0000000000..fefca117d3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/IVisitor.java @@ -0,0 +1,20 @@ +package com.dianping.cat.consumer.cross.model; + +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public interface IVisitor { + + public void visitCrossReport(CrossReport crossReport); + + public void visitLocal(Local local); + + public void visitName(Name name); + + public void visitRemote(Remote remote); + + public void visitType(Type type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/CrossReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/CrossReport.java new file mode 100644 index 0000000000..6047421ece --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/CrossReport.java @@ -0,0 +1,155 @@ +package com.dianping.cat.consumer.cross.model.entity; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_CROSS_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.cross.model.BaseEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; + +public class CrossReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Set m_domainNames = new LinkedHashSet(); + + private Set m_ips = new LinkedHashSet(); + + private Map m_locals = new LinkedHashMap(); + + public CrossReport() { + } + + public CrossReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCrossReport(this); + } + + public CrossReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public CrossReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public CrossReport addLocal(Local local) { + m_locals.put(local.getId(), local); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CrossReport) { + CrossReport _o = (CrossReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Local findLocal(String id) { + return m_locals.get(id); + } + + public Local findOrCreateLocal(String id) { + Local local = m_locals.get(id); + + if (local == null) { + synchronized (m_locals) { + local = m_locals.get(id); + + if (local == null) { + local = new Local(id); + m_locals.put(id, local); + } + } + } + + return local; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Set getIps() { + return m_ips; + } + + public Map getLocals() { + return m_locals; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(CrossReport other) { + assertAttributeEquals(other, ENTITY_CROSS_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Local removeLocal(String id) { + return m_locals.remove(id); + } + + public CrossReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public CrossReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public CrossReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Local.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Local.java new file mode 100644 index 0000000000..b6ef361bc5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Local.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.cross.model.entity; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_LOCAL; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.cross.model.BaseEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; + +public class Local extends BaseEntity { + private String m_id; + + private Map m_remotes = new LinkedHashMap(); + + public Local() { + } + + public Local(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitLocal(this); + } + + public Local addRemote(Remote remote) { + m_remotes.put(remote.getId(), remote); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Local) { + Local _o = (Local) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Remote findRemote(String id) { + return m_remotes.get(id); + } + + public Remote findOrCreateRemote(String id) { + Remote remote = m_remotes.get(id); + + if (remote == null) { + synchronized (m_remotes) { + remote = m_remotes.get(id); + + if (remote == null) { + remote = new Remote(id); + m_remotes.put(id, remote); + } + } + } + + return remote; + } + + public String getId() { + return m_id; + } + + public Map getRemotes() { + return m_remotes; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Local other) { + assertAttributeEquals(other, ENTITY_LOCAL, ATTR_ID, m_id, other.getId()); + + } + + public Remote removeRemote(String id) { + return m_remotes.remove(id); + } + + public Local setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Name.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Name.java new file mode 100644 index 0000000000..096055d3b0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Name.java @@ -0,0 +1,160 @@ +package com.dianping.cat.consumer.cross.model.entity; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_NAME; + +import com.dianping.cat.consumer.cross.model.BaseEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; + +public class Name extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private int m_failCount; + + private double m_failPercent; + + private double m_avg; + + private double m_sum; + + private double m_tps; + + public Name() { + } + + public Name(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitName(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Name) { + Name _o = (Name) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public double getAvg() { + return m_avg; + } + + public int getFailCount() { + return m_failCount; + } + + public double getFailPercent() { + return m_failPercent; + } + + public String getId() { + return m_id; + } + + public double getSum() { + return m_sum; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Name incFailCount() { + m_failCount++; + return this; + } + + public Name incFailCount(int failCount) { + m_failCount += failCount; + return this; + } + + public Name incTotalCount() { + m_totalCount++; + return this; + } + + public Name incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(Name other) { + assertAttributeEquals(other, ENTITY_NAME, ATTR_ID, m_id, other.getId()); + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_tps = other.getTps(); + } + + public Name setAvg(double avg) { + m_avg = avg; + return this; + } + + public Name setFailCount(int failCount) { + m_failCount = failCount; + return this; + } + + public Name setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public Name setId(String id) { + m_id = id; + return this; + } + + public Name setSum(double sum) { + m_sum = sum; + return this; + } + + public Name setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public Name setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Remote.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Remote.java new file mode 100644 index 0000000000..d68eaa341a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Remote.java @@ -0,0 +1,118 @@ +package com.dianping.cat.consumer.cross.model.entity; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_REMOTE; + +import com.dianping.cat.consumer.cross.model.BaseEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; + +public class Remote extends BaseEntity { + private String m_id; + + private String m_role; + + private Type m_type; + + private String m_app; + + private String m_ip; + + public Remote() { + } + + public Remote(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRemote(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Remote) { + Remote _o = (Remote) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getApp() { + return m_app; + } + + public String getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public String getRole() { + return m_role; + } + + public Type getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Remote other) { + assertAttributeEquals(other, ENTITY_REMOTE, ATTR_ID, m_id, other.getId()); + + if (other.getRole() != null) { + m_role = other.getRole(); + } + + if (other.getApp() != null) { + m_app = other.getApp(); + } + + if (other.getIp() != null) { + m_ip = other.getIp(); + } + } + + public Remote setApp(String app) { + m_app = app; + return this; + } + + public Remote setId(String id) { + m_id = id; + return this; + } + + public Remote setIp(String ip) { + m_ip = ip; + return this; + } + + public Remote setRole(String role) { + m_role = role; + return this; + } + + public Remote setType(Type type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Type.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Type.java new file mode 100644 index 0000000000..fb899500a8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/entity/Type.java @@ -0,0 +1,230 @@ +package com.dianping.cat.consumer.cross.model.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.cross.model.BaseEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; + +public class Type extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private int m_failCount; + + private double m_failPercent; + + private double m_avg; + + private double m_sum; + + private double m_tps; + + private Map m_names = new LinkedHashMap(); + + public Type() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitType(this); + } + + public Type addName(Name name) { + m_names.put(name.getId(), name); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Type) { + Type _o = (Type) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + if (getTotalCount() != _o.getTotalCount()) { + return false; + } + + if (getFailCount() != _o.getFailCount()) { + return false; + } + + if (getFailPercent() != _o.getFailPercent()) { + return false; + } + + if (getAvg() != _o.getAvg()) { + return false; + } + + if (getSum() != _o.getSum()) { + return false; + } + + if (getTps() != _o.getTps()) { + return false; + } + + if (!equals(getNames(), _o.getNames())) { + return false; + } + + + return true; + } + + return false; + } + + public Name findName(String id) { + return m_names.get(id); + } + + public Name findOrCreateName(String id) { + Name name = m_names.get(id); + + if (name == null) { + synchronized (m_names) { + name = m_names.get(id); + + if (name == null) { + name = new Name(id); + m_names.put(id, name); + } + } + } + + return name; + } + + public double getAvg() { + return m_avg; + } + + public int getFailCount() { + return m_failCount; + } + + public double getFailPercent() { + return m_failPercent; + } + + public String getId() { + return m_id; + } + + public Map getNames() { + return m_names; + } + + public double getSum() { + return m_sum; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + hash = hash * 31 + (int) (m_totalCount ^ (m_totalCount >>> 32)); + hash = hash * 31 + m_failCount; + hash = hash * 31 + (int) (Double.doubleToLongBits(m_failPercent) ^ (Double.doubleToLongBits(m_failPercent) >>> 32)); + hash = hash * 31 + (int) (Double.doubleToLongBits(m_avg) ^ (Double.doubleToLongBits(m_avg) >>> 32)); + hash = hash * 31 + (int) (Double.doubleToLongBits(m_sum) ^ (Double.doubleToLongBits(m_sum) >>> 32)); + hash = hash * 31 + (int) (Double.doubleToLongBits(m_tps) ^ (Double.doubleToLongBits(m_tps) >>> 32)); + hash = hash * 31 + (m_names == null ? 0 : m_names.hashCode()); + + return hash; + } + + public Type incFailCount() { + m_failCount++; + return this; + } + + public Type incFailCount(int failCount) { + m_failCount += failCount; + return this; + } + + public Type incTotalCount() { + m_totalCount++; + return this; + } + + public Type incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(Type other) { + if (other.getId() != null) { + m_id = other.getId(); + } + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_tps = other.getTps(); + } + + public Name removeName(String id) { + return m_names.remove(id); + } + + public Type setAvg(double avg) { + m_avg = avg; + return this; + } + + public Type setFailCount(int failCount) { + m_failCount = failCount; + return this; + } + + public Type setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public Type setId(String id) { + m_id = id; + return this; + } + + public Type setSum(double sum) { + m_sum = sum; + return this; + } + + public Type setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public Type setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..466de7245f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/BaseVisitor.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import com.dianping.cat.consumer.cross.model.IVisitor; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitCrossReport(CrossReport crossReport) { + for (Local local : crossReport.getLocals().values()) { + visitLocal(local); + } + } + + @Override + public void visitLocal(Local local) { + for (Remote remote : local.getRemotes().values()) { + visitRemote(remote); + } + } + + @Override + public void visitName(Name name) { + } + + @Override + public void visitRemote(Remote remote) { + if (remote.getType() != null) { + visitType(remote.getType()); + } + } + + @Override + public void visitType(Type type) { + for (Name name : type.getNames().values()) { + visitName(name); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..7c7bc44691 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultLinker.java @@ -0,0 +1,79 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onLocal(final CrossReport parent, final Local local) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addLocal(local); + } + }); + } else { + parent.addLocal(local); + } + + return true; + } + + @Override + public boolean onName(final Type parent, final Name name) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addName(name); + } + }); + } else { + parent.addName(name); + } + + return true; + } + + @Override + public boolean onRemote(final Local parent, final Remote remote) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRemote(remote); + } + }); + } else { + parent.addRemote(remote); + } + + return true; + } + + @Override + public boolean onType(final Remote parent, final Type type) { + parent.setType(type); + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..7f3a594c1f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultMerger.java @@ -0,0 +1,165 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.cross.model.IEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private CrossReport m_crossReport; + + public DefaultMerger() { + } + + public DefaultMerger(CrossReport crossReport) { + m_crossReport = crossReport; + m_objs.push(crossReport); + } + + public CrossReport getCrossReport() { + return m_crossReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeCrossReport(CrossReport to, CrossReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + to.getIps().addAll(from.getIps()); + } + + protected void mergeLocal(Local to, Local from) { + to.mergeAttributes(from); + } + + protected void mergeName(Name to, Name from) { + to.mergeAttributes(from); + } + + protected void mergeRemote(Remote to, Remote from) { + to.mergeAttributes(from); + } + + protected void mergeType(Type to, Type from) { + to.mergeAttributes(from); + } + + @Override + public void visitCrossReport(CrossReport from) { + CrossReport to = (CrossReport) m_objs.peek(); + + mergeCrossReport(to, from); + visitCrossReportChildren(to, from); + } + + protected void visitCrossReportChildren(CrossReport to, CrossReport from) { + for (Local source : from.getLocals().values()) { + Local target = to.findLocal(source.getId()); + + if (target == null) { + target = new Local(source.getId()); + to.addLocal(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitLocal(Local from) { + Local to = (Local) m_objs.peek(); + + mergeLocal(to, from); + visitLocalChildren(to, from); + } + + protected void visitLocalChildren(Local to, Local from) { + for (Remote source : from.getRemotes().values()) { + Remote target = to.findRemote(source.getId()); + + if (target == null) { + target = new Remote(source.getId()); + to.addRemote(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitName(Name from) { + Name to = (Name) m_objs.peek(); + + mergeName(to, from); + visitNameChildren(to, from); + } + + protected void visitNameChildren(Name to, Name from) { + } + + @Override + public void visitRemote(Remote from) { + Remote to = (Remote) m_objs.peek(); + + mergeRemote(to, from); + visitRemoteChildren(to, from); + } + + protected void visitRemoteChildren(Remote to, Remote from) { + if (from.getType() != null) { + Type target = to.getType(); + + if (target == null) { + target = new Type(); + to.setType(target); + } + + m_objs.push(target); + from.getType().accept(this); + m_objs.pop(); + } + } + + @Override + public void visitType(Type from) { + Type to = (Type) m_objs.peek(); + + mergeType(to, from); + visitTypeChildren(to, from); + } + + protected void visitTypeChildren(Type to, Type from) { + for (Name source : from.getNames().values()) { + Name target = to.findName(source.getId()); + + if (target == null) { + target = new Name(source.getId()); + to.addName(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..63818b6b37 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,263 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.cross.model.IVisitor; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(CrossReport crossReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(crossReport, out); + return out.toByteArray(); + } + + public static void build(CrossReport crossReport, OutputStream out) { + crossReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitCrossReport(CrossReport crossReport) { + writeTag(63, 0); + + if (crossReport.getDomain() != null) { + writeTag(1, 1); + writeString(crossReport.getDomain()); + } + + if (crossReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(crossReport.getStartTime()); + } + + if (crossReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(crossReport.getEndTime()); + } + + if (crossReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(crossReport.getDomainNames().size()); + + for (String domain : crossReport.getDomainNames()) { + writeString(domain); + } + } + + if (crossReport.getIps() != null) { + writeTag(5, 2); + writeInt(crossReport.getIps().size()); + + for (String ip : crossReport.getIps()) { + writeString(ip); + } + } + + if (!crossReport.getLocals().isEmpty()) { + writeTag(33, 2); + writeInt(crossReport.getLocals().size()); + + for (Local local : crossReport.getLocals().values()) { + local.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitLocal(Local local) { + if (local.getId() != null) { + writeTag(1, 1); + writeString(local.getId()); + } + + if (!local.getRemotes().isEmpty()) { + writeTag(33, 2); + writeInt(local.getRemotes().size()); + + for (Remote remote : local.getRemotes().values()) { + remote.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitName(Name name) { + if (name.getId() != null) { + writeTag(1, 1); + writeString(name.getId()); + } + + writeTag(2, 0); + writeLong(name.getTotalCount()); + + writeTag(3, 0); + writeInt(name.getFailCount()); + + writeTag(4, 0); + writeDouble(name.getFailPercent()); + + writeTag(5, 0); + writeDouble(name.getAvg()); + + writeTag(6, 0); + writeDouble(name.getSum()); + + writeTag(7, 0); + writeDouble(name.getTps()); + + writeTag(63, 3); + } + + @Override + public void visitRemote(Remote remote) { + if (remote.getId() != null) { + writeTag(1, 1); + writeString(remote.getId()); + } + + if (remote.getRole() != null) { + writeTag(2, 1); + writeString(remote.getRole()); + } + + if (remote.getApp() != null) { + writeTag(3, 1); + writeString(remote.getApp()); + } + + if (remote.getIp() != null) { + writeTag(4, 1); + writeString(remote.getIp()); + } + + if (remote.getType() != null) { + writeTag(33, 1); + remote.getType().accept(m_visitor); + } + + writeTag(63, 3); + } + + @Override + public void visitType(Type type) { + if (type.getId() != null) { + writeTag(1, 1); + writeString(type.getId()); + } + + writeTag(2, 0); + writeLong(type.getTotalCount()); + + writeTag(3, 0); + writeInt(type.getFailCount()); + + writeTag(4, 0); + writeDouble(type.getFailPercent()); + + writeTag(5, 0); + writeDouble(type.getAvg()); + + writeTag(6, 0); + writeDouble(type.getSum()); + + writeTag(7, 0); + writeDouble(type.getTps()); + + if (!type.getNames().isEmpty()) { + writeTag(33, 2); + writeInt(type.getNames().size()); + + for (Name name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..406808d44f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultNativeParser.java @@ -0,0 +1,319 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.cross.model.IVisitor; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static CrossReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static CrossReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + CrossReport crossReport = new CrossReport(); + + try { + crossReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return crossReport; + } + + @Override + public void visitCrossReport(CrossReport crossReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitCrossReportChildren(crossReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitCrossReportChildren(CrossReport crossReport, int _field, int _type) { + switch (_field) { + case 1: + crossReport.setDomain(readString()); + break; + case 2: + crossReport.setStartTime(readDate()); + break; + case 3: + crossReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + crossReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + crossReport.addDomain(readString()); + } + } + break; + case 5: + if (_type == 1) { + crossReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + crossReport.addIp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Local local = new Local(); + + visitLocal(local); + m_linker.onLocal(crossReport, local); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Local local = new Local(); + + visitLocal(local); + m_linker.onLocal(crossReport, local); + } + } + break; + } + } + + @Override + public void visitLocal(Local local) { + byte tag; + + while ((tag = readTag()) != -1) { + visitLocalChildren(local, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitLocalChildren(Local local, int _field, int _type) { + switch (_field) { + case 1: + local.setId(readString()); + break; + case 33: + if (_type == 1) { + Remote remote = new Remote(); + + visitRemote(remote); + m_linker.onRemote(local, remote); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Remote remote = new Remote(); + + visitRemote(remote); + m_linker.onRemote(local, remote); + } + } + break; + } + } + + @Override + public void visitName(Name name) { + byte tag; + + while ((tag = readTag()) != -1) { + visitNameChildren(name, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitNameChildren(Name name, int _field, int _type) { + switch (_field) { + case 1: + name.setId(readString()); + break; + case 2: + name.setTotalCount(readLong()); + break; + case 3: + name.setFailCount(readInt()); + break; + case 4: + name.setFailPercent(readDouble()); + break; + case 5: + name.setAvg(readDouble()); + break; + case 6: + name.setSum(readDouble()); + break; + case 7: + name.setTps(readDouble()); + break; + } + } + + @Override + public void visitRemote(Remote remote) { + byte tag; + + while ((tag = readTag()) != -1) { + visitRemoteChildren(remote, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitRemoteChildren(Remote remote, int _field, int _type) { + switch (_field) { + case 1: + remote.setId(readString()); + break; + case 2: + remote.setRole(readString()); + break; + case 3: + remote.setApp(readString()); + break; + case 4: + remote.setIp(readString()); + break; + case 33: + Type type = new Type(); + + visitType(type); + m_linker.onType(remote, type); + break; + } + } + + @Override + public void visitType(Type type) { + byte tag; + + while ((tag = readTag()) != -1) { + visitTypeChildren(type, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitTypeChildren(Type type, int _field, int _type) { + switch (_field) { + case 1: + type.setId(readString()); + break; + case 2: + type.setTotalCount(readLong()); + break; + case 3: + type.setFailCount(readInt()); + break; + case 4: + type.setFailPercent(readDouble()); + break; + case 5: + type.setAvg(readDouble()); + break; + case 6: + type.setSum(readDouble()); + break; + case 7: + type.setTps(readDouble()); + break; + case 33: + if (_type == 1) { + Name name = new Name(); + + visitName(name); + m_linker.onName(type, name); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Name name = new Name(); + + visitName(name); + m_linker.onName(type, name); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..45ccbae405 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxMaker.java @@ -0,0 +1,216 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_APP; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ROLE; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_TPS; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultSaxMaker implements IMaker { + + @Override + public CrossReport buildCrossReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + CrossReport crossReport = new CrossReport(domain); + + if (startTime != null) { + crossReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + crossReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return crossReport; + } + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Local buildLocal(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Local local = new Local(id); + + return local; + } + + @Override + public Name buildName(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String tps = attributes.getValue(ATTR_TPS); + Name name = new Name(id); + + if (totalCount != null) { + name.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + name.setFailCount(convert(Integer.class, failCount, 0)); + } + + if (failPercent != null) { + name.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (avg != null) { + name.setAvg(toNumber(avg, "0.00", 0).doubleValue()); + } + + if (sum != null) { + name.setSum(toNumber(sum, "0.00", 0).doubleValue()); + } + + if (tps != null) { + name.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + return name; + } + + @Override + public Remote buildRemote(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String role = attributes.getValue(ATTR_ROLE); + String app = attributes.getValue(ATTR_APP); + String ip = attributes.getValue(ATTR_IP); + Remote remote = new Remote(id); + + if (role != null) { + remote.setRole(role); + } + + if (app != null) { + remote.setApp(app); + } + + if (ip != null) { + remote.setIp(ip); + } + + return remote; + } + + @Override + public Type buildType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String tps = attributes.getValue(ATTR_TPS); + Type type = new Type(); + + if (id != null) { + type.setId(id); + } + + if (totalCount != null) { + type.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + type.setFailCount(convert(Integer.class, failCount, 0)); + } + + if (failPercent != null) { + type.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (avg != null) { + type.setAvg(toNumber(avg, "0.00", 0).doubleValue()); + } + + if (sum != null) { + type.setSum(toNumber(sum, "0.00", 0).doubleValue()); + } + + if (tps != null) { + type.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..cab4741c7d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultSaxParser.java @@ -0,0 +1,328 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_DOMAIN_NAMES; +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_IPS; + +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_CROSS_REPORT; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_LOCAL; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_REMOTE; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.cross.model.IEntity; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static CrossReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(CrossReport.class, new InputSource(removeBOM(in))); + } + + public static CrossReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(CrossReport.class, new InputSource(removeBOM(reader))); + } + + public static CrossReport parse(String xml) throws SAXException, IOException { + return parseEntity(CrossReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof CrossReport) { + CrossReport crossReport = (CrossReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + crossReport.addDomain(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + crossReport.addIp(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForCrossReport(CrossReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_LOCAL.equals(qName)) { + Local local = m_maker.buildLocal(attributes); + + m_linker.onLocal(parentObj, local); + m_objs.push(local); + } else { + throw new SAXException(String.format("Element(%s) is not expected under cross-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForLocal(Local parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_REMOTE.equals(qName)) { + Remote remote = m_maker.buildRemote(attributes); + + m_linker.onRemote(parentObj, remote); + m_objs.push(remote); + } else { + throw new SAXException(String.format("Element(%s) is not expected under local!", qName)); + } + + m_tags.push(qName); + } + + private void parseForName(Name parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForRemote(Remote parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_linker.onType(parentObj, type); + m_objs.push(type); + } else { + throw new SAXException(String.format("Element(%s) is not expected under remote!", qName)); + } + + m_tags.push(qName); + } + + private void parseForType(Type parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_NAME.equals(qName)) { + Name name = m_maker.buildName(attributes); + + m_linker.onName(parentObj, name); + m_objs.push(name); + } else { + throw new SAXException(String.format("Element(%s) is not expected under type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_CROSS_REPORT.equals(qName)) { + CrossReport crossReport = m_maker.buildCrossReport(attributes); + + m_entity = crossReport; + m_objs.push(crossReport); + m_tags.push(qName); + } else if (ENTITY_LOCAL.equals(qName)) { + Local local = m_maker.buildLocal(attributes); + + m_entity = local; + m_objs.push(local); + m_tags.push(qName); + } else if (ENTITY_REMOTE.equals(qName)) { + Remote remote = m_maker.buildRemote(attributes); + + m_entity = remote; + m_objs.push(remote); + m_tags.push(qName); + } else if (ENTITY_TYPE.equals(qName)) { + Type type = m_maker.buildType(attributes); + + m_entity = type; + m_objs.push(type); + m_tags.push(qName); + } else if (ENTITY_NAME.equals(qName)) { + Name name = m_maker.buildName(attributes); + + m_entity = name; + m_objs.push(name); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof CrossReport) { + parseForCrossReport((CrossReport) parent, tag, qName, attributes); + } else if (parent instanceof Local) { + parseForLocal((Local) parent, tag, qName, attributes); + } else if (parent instanceof Remote) { + parseForRemote((Remote) parent, tag, qName, attributes); + } else if (parent instanceof Type) { + parseForType((Type) parent, tag, qName, attributes); + } else if (parent instanceof Name) { + parseForName((Name) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..bf65f1c106 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,340 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_APP; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_ROLE; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.cross.model.Constants.ATTR_TPS; +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.cross.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_CROSS_REPORT; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_LOCAL; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_REMOTE; +import static com.dianping.cat.consumer.cross.model.Constants.ENTITY_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.cross.model.IEntity; +import com.dianping.cat.consumer.cross.model.IVisitor; +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitCrossReport(CrossReport crossReport) { + startTag(ENTITY_CROSS_REPORT, null, ATTR_DOMAIN, crossReport.getDomain(), ATTR_STARTTIME, toString(crossReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(crossReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!crossReport.getDomainNames().isEmpty()) { + for (String domain : crossReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!crossReport.getIps().isEmpty()) { + for (String ip : crossReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!crossReport.getLocals().isEmpty()) { + for (Local local : crossReport.getLocals().values()) { + local.accept(m_visitor); + } + } + + endTag(ENTITY_CROSS_REPORT); + } + + @Override + public void visitLocal(Local local) { + startTag(ENTITY_LOCAL, null, ATTR_ID, local.getId()); + + if (!local.getRemotes().isEmpty()) { + for (Remote remote : local.getRemotes().values()) { + remote.accept(m_visitor); + } + } + + endTag(ENTITY_LOCAL); + } + + @Override + public void visitName(Name name) { + startTag(ENTITY_NAME, true, null, ATTR_ID, name.getId(), ATTR_TOTALCOUNT, name.getTotalCount(), ATTR_FAILCOUNT, name.getFailCount(), ATTR_FAILPERCENT, toString(name.getFailPercent(), "0.00"), ATTR_AVG, toString(name.getAvg(), "0.00"), ATTR_SUM, toString(name.getSum(), "0.00"), ATTR_TPS, toString(name.getTps(), "0.00")); + } + + @Override + public void visitRemote(Remote remote) { + startTag(ENTITY_REMOTE, null, ATTR_ID, remote.getId(), ATTR_ROLE, remote.getRole(), ATTR_APP, remote.getApp(), ATTR_IP, remote.getIp()); + + if (remote.getType() != null) { + remote.getType().accept(m_visitor); + } + + endTag(ENTITY_REMOTE); + } + + @Override + public void visitType(Type type) { + startTag(ENTITY_TYPE, null, ATTR_ID, type.getId(), ATTR_TOTALCOUNT, type.getTotalCount(), ATTR_FAILCOUNT, type.getFailCount(), ATTR_FAILPERCENT, toString(type.getFailPercent(), "0.00"), ATTR_AVG, toString(type.getAvg(), "0.00"), ATTR_SUM, toString(type.getSum(), "0.00"), ATTR_TPS, toString(type.getTps(), "0.00")); + + if (!type.getNames().isEmpty()) { + for (Name name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + endTag(ENTITY_TYPE); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/ILinker.java new file mode 100644 index 0000000000..d6c624f192 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/ILinker.java @@ -0,0 +1,18 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public interface ILinker { + + public boolean onLocal(CrossReport parent, Local local); + + public boolean onName(Type parent, Name name); + + public boolean onRemote(Local parent, Remote remote); + + public boolean onType(Remote parent, Type type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IMaker.java new file mode 100644 index 0000000000..0a4b86fb33 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IMaker.java @@ -0,0 +1,24 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public interface IMaker { + + public CrossReport buildCrossReport(T node); + + public String buildDomain(T node); + + public String buildIp(T node); + + public Local buildLocal(T node); + + public Name buildName(T node); + + public Remote buildRemote(T node); + + public Type buildType(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IParser.java new file mode 100644 index 0000000000..311fecbbf2 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/cross/model/transform/IParser.java @@ -0,0 +1,19 @@ +package com.dianping.cat.consumer.cross.model.transform; + +import com.dianping.cat.consumer.cross.model.entity.CrossReport; +import com.dianping.cat.consumer.cross.model.entity.Local; +import com.dianping.cat.consumer.cross.model.entity.Name; +import com.dianping.cat.consumer.cross.model.entity.Remote; +import com.dianping.cat.consumer.cross.model.entity.Type; + +public interface IParser { + public CrossReport parse(IMaker maker, ILinker linker, T node); + + public void parseForLocal(IMaker maker, ILinker linker, Local parent, T node); + + public void parseForName(IMaker maker, ILinker linker, Name parent, T node); + + public void parseForRemote(IMaker maker, ILinker linker, Remote parent, T node); + + public void parseForType(IMaker maker, ILinker linker, Type parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyAnalyzer.java index 0aa364d4f4..64fe596b94 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyAnalyzer.java @@ -19,7 +19,9 @@ package com.dianping.cat.consumer.dependency; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.consumer.DatabaseParser; import com.dianping.cat.consumer.DatabaseParser.Database; @@ -33,60 +35,55 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -@Named(type = MessageAnalyzer.class, value = DependencyAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class DependencyAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + DependencyAnalyzer.ID) +@Scope("prototype") +public class DependencyAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "dependency"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = DependencyAnalyzer.ID + "ReportManager") + private ReportManager dependencyReportManager; - @Inject - private ServerFilterConfigManager m_serverFilterConfigManager; + @Resource(name = "serverFilterConfigManager") + private ServerFilterConfigManager serverFilterConfigManager; - @Inject - private DatabaseParser m_parser; + @Resource(name = "databaseParser") + private DatabaseParser databaseParser; - private Set m_types = new HashSet( + private Set types = new HashSet( Arrays.asList("URL", "SQL", "Call", "PigeonCall", "Service", "PigeonService")); - private Set m_exceptions = new HashSet(Arrays.asList("Exception", "RuntimeException", "Error")); + private Set exceptions = new HashSet(Arrays.asList("Exception", "RuntimeException", "Error")); @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + dependencyReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + dependencyReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - private DependencyReport findOrCreateReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, true); + return dependencyReportManager.getHourlyReport(getStartTime(), domain, true); } @Override public DependencyReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, false); + return dependencyReportManager.getHourlyReport(getStartTime(), domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return dependencyReportManager; } private boolean isCache(String type) { @@ -104,7 +101,7 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + dependencyReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } private String parseDatabase(Transaction t) { @@ -115,7 +112,7 @@ private String parseDatabase(Transaction t) { String type = message.getType(); if (type.equals("SQL.Database")) { - Database database = m_parser.parseDatabase(message.getName()); + Database database = databaseParser.parseDatabase(message.getName()); return database != null ? database.getName() : null; } @@ -152,7 +149,7 @@ public void process(MessageTree tree) { private void processEvent(DependencyReport report, MessageTree tree, Event event) { String type = event.getType(); - if (m_exceptions.contains(type)) { + if (exceptions.contains(type)) { long current = event.getTimestamp() / 1000 / 60; int min = (int) (current % (60)); Segment segment = report.findOrCreateSegment(min); @@ -206,7 +203,7 @@ private void processTransaction(DependencyReport report, MessageTree tree, Trans } private void processTransactionType(DependencyReport report, Transaction t, String type) { - if (m_types.contains(type) || isCache(type)) { + if (types.contains(type) || isCache(type)) { long current = t.getTimestamp() / 1000 / 60; int min = (int) (current % (60)); Segment segment = report.findOrCreateSegment(min); @@ -244,4 +241,10 @@ private void updateDependencyInfo(DependencyReport report, Transaction t, String } } + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyDelegate.java index c912c64734..a6546a53f0 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/DependencyDelegate.java @@ -26,16 +26,12 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = DependencyAnalyzer.ID) public class DependencyDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; @Override @@ -93,4 +89,8 @@ public DependencyReport parseBinary(byte[] bytes) { public DependencyReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/BaseEntity.java new file mode 100644 index 0000000000..1dc200c32a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.dependency.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.dependency.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/Constants.java new file mode 100644 index 0000000000..dabbba26b2 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/Constants.java @@ -0,0 +1,48 @@ +package com.dianping.cat.consumer.dependency.model; + +public class Constants { + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_ERROR_COUNT = "error-count"; + + public static final String ATTR_EXCEPTION_COUNT = "exception-count"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_KEY = "key"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_SUM = "sum"; + + public static final String ATTR_TARGET = "target"; + + public static final String ATTR_TOTAL_COUNT = "total-count"; + + public static final String ATTR_TYPE = "type"; + + public static final String ELEMENT_DOMAINNAME = "domainName"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ENTITY_DEPENDENCY = "dependency"; + + public static final String ENTITY_DEPENDENCIES = "dependencies"; + + public static final String ENTITY_DEPENDENCY_REPORT = "dependency-report"; + + public static final String ENTITY_INDEX = "index"; + + public static final String ENTITY_INDEXS = "indexs"; + + public static final String ENTITY_SEGMENT = "segment"; + + public static final String ENTITY_SEGMENTS = "segments"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IEntity.java new file mode 100644 index 0000000000..7a7a2c1c86 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.dependency.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IVisitor.java new file mode 100644 index 0000000000..e6348098b0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/IVisitor.java @@ -0,0 +1,17 @@ +package com.dianping.cat.consumer.dependency.model; + +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public interface IVisitor { + + public void visitDependency(Dependency dependency); + + public void visitDependencyReport(DependencyReport dependencyReport); + + public void visitIndex(Index index); + + public void visitSegment(Segment segment); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Dependency.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Dependency.java new file mode 100644 index 0000000000..53aa290717 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Dependency.java @@ -0,0 +1,164 @@ +package com.dianping.cat.consumer.dependency.model.entity; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_KEY; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY; + +import com.dianping.cat.consumer.dependency.model.BaseEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; + +public class Dependency extends BaseEntity { + private String m_type; + + private String m_target; + + private long m_totalCount; + + private double m_avg; + + private long m_errorCount; + + private String m_key; + + private double m_sum; + + public Dependency() { + } + + public Dependency(String key) { + m_key = key; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDependency(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Dependency) { + Dependency _o = (Dependency) obj; + + if (!equals(getKey(), _o.getKey())) { + return false; + } + + return true; + } + + return false; + } + + public double getAvg() { + return m_avg; + } + + public long getErrorCount() { + return m_errorCount; + } + + public String getKey() { + return m_key; + } + + public double getSum() { + return m_sum; + } + + public String getTarget() { + return m_target; + } + + public long getTotalCount() { + return m_totalCount; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_key == null ? 0 : m_key.hashCode()); + + return hash; + } + + public Dependency incErrorCount() { + m_errorCount++; + return this; + } + + public Dependency incErrorCount(long errorCount) { + m_errorCount += errorCount; + return this; + } + + public Dependency incTotalCount() { + m_totalCount++; + return this; + } + + public Dependency incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(Dependency other) { + assertAttributeEquals(other, ENTITY_DEPENDENCY, ATTR_KEY, m_key, other.getKey()); + + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getTarget() != null) { + m_target = other.getTarget(); + } + + m_totalCount = other.getTotalCount(); + + m_avg = other.getAvg(); + + m_errorCount = other.getErrorCount(); + + m_sum = other.getSum(); + } + + public Dependency setAvg(double avg) { + m_avg = avg; + return this; + } + + public Dependency setErrorCount(long errorCount) { + m_errorCount = errorCount; + return this; + } + + public Dependency setKey(String key) { + m_key = key; + return this; + } + + public Dependency setSum(double sum) { + m_sum = sum; + return this; + } + + public Dependency setTarget(String target) { + m_target = target; + return this; + } + + public Dependency setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public Dependency setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/DependencyReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/DependencyReport.java new file mode 100644 index 0000000000..28941f1a64 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/DependencyReport.java @@ -0,0 +1,144 @@ +package com.dianping.cat.consumer.dependency.model.entity; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.dependency.model.BaseEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; + +public class DependencyReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_segments = new LinkedHashMap(); + + private Set m_domainNames = new LinkedHashSet(); + + public DependencyReport() { + } + + public DependencyReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDependencyReport(this); + } + + public DependencyReport addDomainName(String domainName) { + m_domainNames.add(domainName); + return this; + } + + public DependencyReport addSegment(Segment segment) { + m_segments.put(segment.getId(), segment); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DependencyReport) { + DependencyReport _o = (DependencyReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Segment findSegment(Integer id) { + return m_segments.get(id); + } + + public Segment findOrCreateSegment(Integer id) { + Segment segment = m_segments.get(id); + + if (segment == null) { + synchronized (m_segments) { + segment = m_segments.get(id); + + if (segment == null) { + segment = new Segment(id); + m_segments.put(id, segment); + } + } + } + + return segment; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Map getSegments() { + return m_segments; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(DependencyReport other) { + assertAttributeEquals(other, ENTITY_DEPENDENCY_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Segment removeSegment(Integer id) { + return m_segments.remove(id); + } + + public DependencyReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public DependencyReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public DependencyReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Index.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Index.java new file mode 100644 index 0000000000..4784e4af5c --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Index.java @@ -0,0 +1,134 @@ +package com.dianping.cat.consumer.dependency.model.entity; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_INDEX; + +import com.dianping.cat.consumer.dependency.model.BaseEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; + +public class Index extends BaseEntity { + private String m_name; + + private long m_totalCount; + + private long m_errorCount; + + private double m_sum; + + private double m_avg; + + public Index() { + } + + public Index(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitIndex(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Index) { + Index _o = (Index) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public double getAvg() { + return m_avg; + } + + public long getErrorCount() { + return m_errorCount; + } + + public String getName() { + return m_name; + } + + public double getSum() { + return m_sum; + } + + public long getTotalCount() { + return m_totalCount; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + public Index incErrorCount() { + m_errorCount++; + return this; + } + + public Index incErrorCount(long errorCount) { + m_errorCount += errorCount; + return this; + } + + public Index incTotalCount() { + m_totalCount++; + return this; + } + + public Index incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(Index other) { + assertAttributeEquals(other, ENTITY_INDEX, ATTR_NAME, m_name, other.getName()); + + m_totalCount = other.getTotalCount(); + + m_errorCount = other.getErrorCount(); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + } + + public Index setAvg(double avg) { + m_avg = avg; + return this; + } + + public Index setErrorCount(long errorCount) { + m_errorCount = errorCount; + return this; + } + + public Index setName(String name) { + m_name = name; + return this; + } + + public Index setSum(double sum) { + m_sum = sum; + return this; + } + + public Index setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Segment.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Segment.java new file mode 100644 index 0000000000..bc8dd292f8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/entity/Segment.java @@ -0,0 +1,152 @@ +package com.dianping.cat.consumer.dependency.model.entity; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_SEGMENT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.dependency.model.BaseEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; + +public class Segment extends BaseEntity { + private Integer m_id; + + private Integer m_exceptionCount; + + private Map m_indexs = new LinkedHashMap(); + + private Map m_dependencies = new LinkedHashMap(); + + public Segment() { + } + + public Segment(Integer id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSegment(this); + } + + public Segment addDependency(Dependency dependency) { + m_dependencies.put(dependency.getKey(), dependency); + return this; + } + + public Segment addIndex(Index index) { + m_indexs.put(index.getName(), index); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Segment) { + Segment _o = (Segment) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Dependency findDependency(String key) { + return m_dependencies.get(key); + } + + public Index findIndex(String name) { + return m_indexs.get(name); + } + + public Dependency findOrCreateDependency(String key) { + Dependency dependency = m_dependencies.get(key); + + if (dependency == null) { + synchronized (m_dependencies) { + dependency = m_dependencies.get(key); + + if (dependency == null) { + dependency = new Dependency(key); + m_dependencies.put(key, dependency); + } + } + } + + return dependency; + } + + public Index findOrCreateIndex(String name) { + Index index = m_indexs.get(name); + + if (index == null) { + synchronized (m_indexs) { + index = m_indexs.get(name); + + if (index == null) { + index = new Index(name); + m_indexs.put(name, index); + } + } + } + + return index; + } + + public Map getDependencies() { + return m_dependencies; + } + + public Integer getExceptionCount() { + return m_exceptionCount; + } + + public Integer getId() { + return m_id; + } + + public Map getIndexs() { + return m_indexs; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Segment other) { + assertAttributeEquals(other, ENTITY_SEGMENT, ATTR_ID, m_id, other.getId()); + + if (other.getExceptionCount() != null) { + m_exceptionCount = other.getExceptionCount(); + } + } + + public Dependency removeDependency(String key) { + return m_dependencies.remove(key); + } + + public Index removeIndex(String name) { + return m_indexs.remove(name); + } + + public Segment setExceptionCount(Integer exceptionCount) { + m_exceptionCount = exceptionCount; + return this; + } + + public Segment setId(Integer id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..00b05a9c8c --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/BaseVisitor.java @@ -0,0 +1,35 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import com.dianping.cat.consumer.dependency.model.IVisitor; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDependency(Dependency dependency) { + } + + @Override + public void visitDependencyReport(DependencyReport dependencyReport) { + for (Segment segment : dependencyReport.getSegments().values()) { + visitSegment(segment); + } + } + + @Override + public void visitIndex(Index index) { + } + + @Override + public void visitSegment(Segment segment) { + for (Index index : segment.getIndexs().values()) { + visitIndex(index); + } + + for (Dependency dependency : segment.getDependencies().values()) { + visitDependency(dependency); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..924e12ba18 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultLinker.java @@ -0,0 +1,72 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDependency(final Segment parent, final Dependency dependency) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDependency(dependency); + } + }); + } else { + parent.addDependency(dependency); + } + + return true; + } + + @Override + public boolean onIndex(final Segment parent, final Index index) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addIndex(index); + } + }); + } else { + parent.addIndex(index); + } + + return true; + } + + @Override + public boolean onSegment(final DependencyReport parent, final Segment segment) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSegment(segment); + } + }); + } else { + parent.addSegment(segment); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..6a14aa4116 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultMerger.java @@ -0,0 +1,137 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.dependency.model.IEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private DependencyReport m_dependencyReport; + + public DefaultMerger() { + } + + public DefaultMerger(DependencyReport dependencyReport) { + m_dependencyReport = dependencyReport; + m_objs.push(dependencyReport); + } + + public DependencyReport getDependencyReport() { + return m_dependencyReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDependency(Dependency to, Dependency from) { + to.mergeAttributes(from); + } + + protected void mergeDependencyReport(DependencyReport to, DependencyReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + } + + protected void mergeIndex(Index to, Index from) { + to.mergeAttributes(from); + } + + protected void mergeSegment(Segment to, Segment from) { + to.mergeAttributes(from); + } + + @Override + public void visitDependency(Dependency from) { + Dependency to = (Dependency) m_objs.peek(); + + mergeDependency(to, from); + visitDependencyChildren(to, from); + } + + protected void visitDependencyChildren(Dependency to, Dependency from) { + } + + @Override + public void visitDependencyReport(DependencyReport from) { + DependencyReport to = (DependencyReport) m_objs.peek(); + + mergeDependencyReport(to, from); + visitDependencyReportChildren(to, from); + } + + protected void visitDependencyReportChildren(DependencyReport to, DependencyReport from) { + for (Segment source : from.getSegments().values()) { + Segment target = to.findSegment(source.getId()); + + if (target == null) { + target = new Segment(source.getId()); + to.addSegment(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitIndex(Index from) { + Index to = (Index) m_objs.peek(); + + mergeIndex(to, from); + visitIndexChildren(to, from); + } + + protected void visitIndexChildren(Index to, Index from) { + } + + @Override + public void visitSegment(Segment from) { + Segment to = (Segment) m_objs.peek(); + + mergeSegment(to, from); + visitSegmentChildren(to, from); + } + + protected void visitSegmentChildren(Segment to, Segment from) { + for (Index source : from.getIndexs().values()) { + Index target = to.findIndex(source.getName()); + + if (target == null) { + target = new Index(source.getName()); + to.addIndex(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Dependency source : from.getDependencies().values()) { + Dependency target = to.findDependency(source.getKey()); + + if (target == null) { + target = new Dependency(source.getKey()); + to.addDependency(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..59b34e46a0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,226 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.dependency.model.IVisitor; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(DependencyReport dependencyReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(dependencyReport, out); + return out.toByteArray(); + } + + public static void build(DependencyReport dependencyReport, OutputStream out) { + dependencyReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDependency(Dependency dependency) { + if (dependency.getType() != null) { + writeTag(1, 1); + writeString(dependency.getType()); + } + + if (dependency.getTarget() != null) { + writeTag(2, 1); + writeString(dependency.getTarget()); + } + + writeTag(3, 0); + writeLong(dependency.getTotalCount()); + + writeTag(4, 0); + writeDouble(dependency.getAvg()); + + writeTag(5, 0); + writeLong(dependency.getErrorCount()); + + if (dependency.getKey() != null) { + writeTag(6, 1); + writeString(dependency.getKey()); + } + + writeTag(7, 0); + writeDouble(dependency.getSum()); + + writeTag(63, 3); + } + + @Override + public void visitDependencyReport(DependencyReport dependencyReport) { + writeTag(63, 0); + + if (dependencyReport.getDomain() != null) { + writeTag(1, 1); + writeString(dependencyReport.getDomain()); + } + + if (dependencyReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(dependencyReport.getStartTime()); + } + + if (dependencyReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(dependencyReport.getEndTime()); + } + + if (dependencyReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(dependencyReport.getDomainNames().size()); + + for (String domainName : dependencyReport.getDomainNames()) { + writeString(domainName); + } + } + + if (!dependencyReport.getSegments().isEmpty()) { + writeTag(33, 2); + writeInt(dependencyReport.getSegments().size()); + + for (Segment segment : dependencyReport.getSegments().values()) { + segment.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitIndex(Index index) { + if (index.getName() != null) { + writeTag(1, 1); + writeString(index.getName()); + } + + writeTag(2, 0); + writeLong(index.getTotalCount()); + + writeTag(3, 0); + writeLong(index.getErrorCount()); + + writeTag(4, 0); + writeDouble(index.getSum()); + + writeTag(5, 0); + writeDouble(index.getAvg()); + + writeTag(63, 3); + } + + @Override + public void visitSegment(Segment segment) { + if (segment.getId() != null) { + writeTag(1, 1); + writeInt(segment.getId()); + } + + if (segment.getExceptionCount() != null) { + writeTag(2, 1); + writeInt(segment.getExceptionCount()); + } + + if (!segment.getIndexs().isEmpty()) { + writeTag(33, 2); + writeInt(segment.getIndexs().size()); + + for (Index index : segment.getIndexs().values()) { + index.accept(m_visitor); + } + } + + if (!segment.getDependencies().isEmpty()) { + writeTag(34, 2); + writeInt(segment.getDependencies().size()); + + for (Dependency dependency : segment.getDependencies().values()) { + dependency.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..41bd6ee9dd --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultNativeParser.java @@ -0,0 +1,274 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.dependency.model.IVisitor; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static DependencyReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static DependencyReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + DependencyReport dependencyReport = new DependencyReport(); + + try { + dependencyReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return dependencyReport; + } + + @Override + public void visitDependency(Dependency dependency) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDependencyChildren(dependency, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDependencyChildren(Dependency dependency, int _field, int _type) { + switch (_field) { + case 1: + dependency.setType(readString()); + break; + case 2: + dependency.setTarget(readString()); + break; + case 3: + dependency.setTotalCount(readLong()); + break; + case 4: + dependency.setAvg(readDouble()); + break; + case 5: + dependency.setErrorCount(readLong()); + break; + case 6: + dependency.setKey(readString()); + break; + case 7: + dependency.setSum(readDouble()); + break; + } + } + + @Override + public void visitDependencyReport(DependencyReport dependencyReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitDependencyReportChildren(dependencyReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDependencyReportChildren(DependencyReport dependencyReport, int _field, int _type) { + switch (_field) { + case 1: + dependencyReport.setDomain(readString()); + break; + case 2: + dependencyReport.setStartTime(readDate()); + break; + case 3: + dependencyReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + dependencyReport.addDomainName(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + dependencyReport.addDomainName(readString()); + } + } + break; + case 33: + if (_type == 1) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(dependencyReport, segment); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(dependencyReport, segment); + } + } + break; + } + } + + @Override + public void visitIndex(Index index) { + byte tag; + + while ((tag = readTag()) != -1) { + visitIndexChildren(index, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitIndexChildren(Index index, int _field, int _type) { + switch (_field) { + case 1: + index.setName(readString()); + break; + case 2: + index.setTotalCount(readLong()); + break; + case 3: + index.setErrorCount(readLong()); + break; + case 4: + index.setSum(readDouble()); + break; + case 5: + index.setAvg(readDouble()); + break; + } + } + + @Override + public void visitSegment(Segment segment) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSegmentChildren(segment, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSegmentChildren(Segment segment, int _field, int _type) { + switch (_field) { + case 1: + segment.setId(readInt()); + break; + case 2: + segment.setExceptionCount(readInt()); + break; + case 33: + if (_type == 1) { + Index index = new Index(); + + visitIndex(index); + m_linker.onIndex(segment, index); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Index index = new Index(); + + visitIndex(index); + m_linker.onIndex(segment, index); + } + } + break; + case 34: + if (_type == 1) { + Dependency dependency = new Dependency(); + + visitDependency(dependency); + m_linker.onDependency(segment, dependency); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Dependency dependency = new Dependency(); + + visitDependency(dependency); + m_linker.onDependency(segment, dependency); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..ed1c241a07 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxMaker.java @@ -0,0 +1,178 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ERROR_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_EXCEPTION_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_KEY; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TARGET; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TOTAL_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TYPE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Dependency buildDependency(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String target = attributes.getValue(ATTR_TARGET); + String totalCount = attributes.getValue(ATTR_TOTAL_COUNT); + String avg = attributes.getValue(ATTR_AVG); + String errorCount = attributes.getValue(ATTR_ERROR_COUNT); + String key = attributes.getValue(ATTR_KEY); + String sum = attributes.getValue(ATTR_SUM); + Dependency dependency = new Dependency(key); + + if (type != null) { + dependency.setType(type); + } + + if (target != null) { + dependency.setTarget(target); + } + + if (totalCount != null) { + dependency.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (avg != null) { + dependency.setAvg(toNumber(avg, "0.00", 0).doubleValue()); + } + + if (errorCount != null) { + dependency.setErrorCount(convert(Long.class, errorCount, 0L)); + } + + if (sum != null) { + dependency.setSum(toNumber(sum, "0.00", 0).doubleValue()); + } + + return dependency; + } + + @Override + public DependencyReport buildDependencyReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + DependencyReport dependencyReport = new DependencyReport(domain); + + if (startTime != null) { + dependencyReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + dependencyReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return dependencyReport; + } + + @Override + public String buildDomainName(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Index buildIndex(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + String totalCount = attributes.getValue(ATTR_TOTAL_COUNT); + String errorCount = attributes.getValue(ATTR_ERROR_COUNT); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + Index index = new Index(name); + + if (totalCount != null) { + index.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (errorCount != null) { + index.setErrorCount(convert(Long.class, errorCount, 0L)); + } + + if (sum != null) { + index.setSum(toNumber(sum, "0.00", 0).doubleValue()); + } + + if (avg != null) { + index.setAvg(toNumber(avg, "0.00", 0).doubleValue()); + } + + return index; + } + + @Override + public Segment buildSegment(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String exceptionCount = attributes.getValue(ATTR_EXCEPTION_COUNT); + Segment segment = new Segment(id == null ? null : convert(Integer.class, id, null)); + + if (exceptionCount != null) { + segment.setExceptionCount(convert(Integer.class, exceptionCount, null)); + } + + return segment; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..53781c7689 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultSaxParser.java @@ -0,0 +1,298 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import static com.dianping.cat.consumer.dependency.model.Constants.ELEMENT_DOMAINNAME; +import static com.dianping.cat.consumer.dependency.model.Constants.ELEMENT_DOMAIN_NAMES; + +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY_REPORT; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_INDEX; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_SEGMENT; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.dependency.model.IEntity; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static DependencyReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(DependencyReport.class, new InputSource(removeBOM(in))); + } + + public static DependencyReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(DependencyReport.class, new InputSource(removeBOM(reader))); + } + + public static DependencyReport parse(String xml) throws SAXException, IOException { + return parseEntity(DependencyReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof DependencyReport) { + DependencyReport dependencyReport = (DependencyReport) currentObj; + + if (ELEMENT_DOMAINNAME.equals(currentTag)) { + dependencyReport.addDomainName(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDependency(Dependency parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForDependencyReport(DependencyReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAINNAME.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_linker.onSegment(parentObj, segment); + m_objs.push(segment); + } else { + throw new SAXException(String.format("Element(%s) is not expected under dependency-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForIndex(Index parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForSegment(Segment parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_INDEX.equals(qName)) { + Index index = m_maker.buildIndex(attributes); + + m_linker.onIndex(parentObj, index); + m_objs.push(index); + } else if (ENTITY_DEPENDENCY.equals(qName)) { + Dependency dependency = m_maker.buildDependency(attributes); + + m_linker.onDependency(parentObj, dependency); + m_objs.push(dependency); + } else { + throw new SAXException(String.format("Element(%s) is not expected under segment!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_DEPENDENCY_REPORT.equals(qName)) { + DependencyReport dependencyReport = m_maker.buildDependencyReport(attributes); + + m_entity = dependencyReport; + m_objs.push(dependencyReport); + m_tags.push(qName); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_entity = segment; + m_objs.push(segment); + m_tags.push(qName); + } else if (ENTITY_INDEX.equals(qName)) { + Index index = m_maker.buildIndex(attributes); + + m_entity = index; + m_objs.push(index); + m_tags.push(qName); + } else if (ENTITY_DEPENDENCY.equals(qName)) { + Dependency dependency = m_maker.buildDependency(attributes); + + m_entity = dependency; + m_objs.push(dependency); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof DependencyReport) { + parseForDependencyReport((DependencyReport) parent, tag, qName, attributes); + } else if (parent instanceof Segment) { + parseForSegment((Segment) parent, tag, qName, attributes); + } else if (parent instanceof Index) { + parseForIndex((Index) parent, tag, qName, attributes); + } else if (parent instanceof Dependency) { + parseForDependency((Dependency) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..79bbd957c8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,318 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ERROR_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_EXCEPTION_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_KEY; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TARGET; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TOTAL_COUNT; +import static com.dianping.cat.consumer.dependency.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.dependency.model.Constants.ELEMENT_DOMAINNAME; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_DEPENDENCY_REPORT; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_INDEX; +import static com.dianping.cat.consumer.dependency.model.Constants.ENTITY_SEGMENT; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.dependency.model.IEntity; +import com.dianping.cat.consumer.dependency.model.IVisitor; +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitDependency(Dependency dependency) { + startTag(ENTITY_DEPENDENCY, true, null, ATTR_TYPE, dependency.getType(), ATTR_TARGET, dependency.getTarget(), ATTR_TOTAL_COUNT, dependency.getTotalCount(), ATTR_AVG, toString(dependency.getAvg(), "0.00"), ATTR_ERROR_COUNT, dependency.getErrorCount(), ATTR_KEY, dependency.getKey(), ATTR_SUM, toString(dependency.getSum(), "0.00")); + } + + @Override + public void visitDependencyReport(DependencyReport dependencyReport) { + startTag(ENTITY_DEPENDENCY_REPORT, null, ATTR_DOMAIN, dependencyReport.getDomain(), ATTR_STARTTIME, toString(dependencyReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(dependencyReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!dependencyReport.getDomainNames().isEmpty()) { + for (String domainName : dependencyReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAINNAME, domainName); + } + } + + if (!dependencyReport.getSegments().isEmpty()) { + for (Segment segment : dependencyReport.getSegments().values()) { + segment.accept(m_visitor); + } + } + + endTag(ENTITY_DEPENDENCY_REPORT); + } + + @Override + public void visitIndex(Index index) { + startTag(ENTITY_INDEX, true, null, ATTR_NAME, index.getName(), ATTR_TOTAL_COUNT, index.getTotalCount(), ATTR_ERROR_COUNT, index.getErrorCount(), ATTR_SUM, toString(index.getSum(), "0.00"), ATTR_AVG, toString(index.getAvg(), "0.00")); + } + + @Override + public void visitSegment(Segment segment) { + startTag(ENTITY_SEGMENT, null, ATTR_ID, segment.getId(), ATTR_EXCEPTION_COUNT, segment.getExceptionCount()); + + if (!segment.getIndexs().isEmpty()) { + for (Index index : segment.getIndexs().values()) { + index.accept(m_visitor); + } + } + + if (!segment.getDependencies().isEmpty()) { + for (Dependency dependency : segment.getDependencies().values()) { + dependency.accept(m_visitor); + } + } + + endTag(ENTITY_SEGMENT); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/ILinker.java new file mode 100644 index 0000000000..8b7ae76278 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/ILinker.java @@ -0,0 +1,15 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public interface ILinker { + + public boolean onDependency(Segment parent, Dependency dependency); + + public boolean onIndex(Segment parent, Index index); + + public boolean onSegment(DependencyReport parent, Segment segment); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IMaker.java new file mode 100644 index 0000000000..7106278395 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IMaker.java @@ -0,0 +1,19 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public interface IMaker { + + public Dependency buildDependency(T node); + + public DependencyReport buildDependencyReport(T node); + + public String buildDomainName(T node); + + public Index buildIndex(T node); + + public Segment buildSegment(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IParser.java new file mode 100644 index 0000000000..0ed909cde2 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dependency/model/transform/IParser.java @@ -0,0 +1,16 @@ +package com.dianping.cat.consumer.dependency.model.transform; + +import com.dianping.cat.consumer.dependency.model.entity.Dependency; +import com.dianping.cat.consumer.dependency.model.entity.DependencyReport; +import com.dianping.cat.consumer.dependency.model.entity.Index; +import com.dianping.cat.consumer.dependency.model.entity.Segment; + +public interface IParser { + public DependencyReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDependency(IMaker maker, ILinker linker, Dependency parent, T node); + + public void parseForIndex(IMaker maker, ILinker linker, Index parent, T node); + + public void parseForSegment(IMaker maker, ILinker linker, Segment parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/BlockDumper.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/BlockDumper.java index bd4a0c99ba..655ee29316 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/BlockDumper.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/BlockDumper.java @@ -24,7 +24,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.unidal.helper.Threads.Task; +import com.dianping.cat.support.Threads.Task; import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/DumpAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/DumpAnalyzer.java index 8ad40e945f..75e937a1d9 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/DumpAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/DumpAnalyzer.java @@ -20,50 +20,59 @@ import com.dianping.cat.Cat; import com.dianping.cat.analysis.AbstractMessageAnalyzer; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.Transaction; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.message.tree.MessageId; import com.dianping.cat.report.ReportManager; import com.dianping.cat.statistic.ServerStatisticManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; +import com.dianping.cat.support.Threads; +import jakarta.annotation.Resource; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; import org.unidal.cat.message.storage.MessageDumper; import org.unidal.cat.message.storage.MessageDumperManager; import org.unidal.cat.message.storage.MessageFinderManager; -import org.unidal.helper.Threads; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.concurrent.TimeUnit; -@Named(type = MessageAnalyzer.class, value = DumpAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class DumpAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + DumpAnalyzer.ID) +@Scope("prototype") +public class DumpAnalyzer extends AbstractMessageAnalyzer { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DumpAnalyzer.class); + public static final String ID = "dump"; - @Inject - private ServerStatisticManager m_serverStateManager; - @Inject - private MessageDumperManager m_dumperManager; + @Resource(name = "serverStatisticManager") + private ServerStatisticManager serverStatisticManager; + + @Resource(name = "messageDumperManager") + private MessageDumperManager dumperManager; - @Inject - private MessageFinderManager m_finderManager; + @Resource(name = "messageFinderManager") + private MessageFinderManager finderManager; - private Logger m_logger; + private int discardSize = 50000000; - private int m_discradSize = 50000000; + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } private void closeStorage() { int hour = (int) TimeUnit.MILLISECONDS.toHours(m_startTime); Transaction t = Cat.newTransaction("Dumper", "Storage" + hour); try { - m_finderManager.close(hour); - m_dumperManager.close(hour); + finderManager.close(hour); + dumperManager.close(hour); t.setStatus(Transaction.SUCCESS); } catch (Exception e) { - m_logger.error(e.getMessage(), e); + LOGGER.error("Unable to close message storage, hour={}.", hour, e); t.setStatus(e); } finally { t.complete(); @@ -84,11 +93,6 @@ public void run() { } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public Object getReport(String domain) { throw new UnsupportedOperationException("This should not be called!"); @@ -104,7 +108,7 @@ public void initialize(long startTime, long duration, long extraTime) { super.initialize(startTime, duration, extraTime); int hour = (int) TimeUnit.MILLISECONDS.toHours(startTime); - m_dumperManager.findOrCreate(hour); + dumperManager.findOrCreate(hour); } @Override @@ -125,25 +129,33 @@ public void process(MessageTree tree) { } private void processWithStorage(MessageTree tree, MessageId messageId, int hour) { - MessageDumper dumper = m_dumperManager.find(hour); + MessageDumper dumper = dumperManager.find(hour); tree.setFormatMessageId(messageId); if (dumper != null) { dumper.process(tree); } else { - m_serverStateManager.addPigeonTimeError(1); + serverStatisticManager.addPigeonTimeError(1); } } - public void setServerStateManager(ServerStatisticManager serverStateManager) { - m_serverStateManager = serverStateManager; + public void setDumperManager(MessageDumperManager dumperManager) { + this.dumperManager = dumperManager; + } + + public void setFinderManager(MessageFinderManager finderManager) { + this.finderManager = finderManager; + } + + public void setServerStatisticManager(ServerStatisticManager serverStatisticManager) { + this.serverStatisticManager = serverStatisticManager; } private boolean shouldDiscard(MessageId id) { int index = id.getIndex(); - return index > m_discradSize; + return index > discardSize; } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/LocalMessageBucketManager.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/LocalMessageBucketManager.java index 0d9248847d..65b5a5bd54 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/LocalMessageBucketManager.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/dump/LocalMessageBucketManager.java @@ -19,10 +19,15 @@ package com.dianping.cat.consumer.dump; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Set; import java.util.concurrent.BlockingQueue; @@ -30,17 +35,11 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; +import java.util.stream.Stream; -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.Scanners; -import org.unidal.helper.Scanners.FileMatcher; -import org.unidal.helper.Threads; -import org.unidal.helper.Threads.Task; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; +import com.dianping.cat.support.Threads; +import com.dianping.cat.support.Threads.Task; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.CatConstants; @@ -54,31 +53,31 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.message.storage.LocalMessageBucket; import com.dianping.cat.message.storage.MessageBlock; -import com.dianping.cat.message.storage.MessageBucket; +import com.dianping.cat.message.storage.MessageBucketFactory; import com.dianping.cat.message.storage.MessageBucketManager; import com.dianping.cat.message.tree.MessageId; import com.dianping.cat.statistic.ServerStatisticManager; import io.netty.buffer.ByteBuf; -public class LocalMessageBucketManager extends ContainerHolder - implements MessageBucketManager, Initializable, LogEnabled { +public class LocalMessageBucketManager implements MessageBucketManager { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(LocalMessageBucketManager.class); public static final String ID = "local"; - protected Logger m_logger; - - @Inject private ServerConfigManager m_configManager; - @Inject private ServerStatisticManager m_serverStateManager; - @Inject private PathBuilder m_pathBuilder; + private MessageBucketFactory m_bucketFactory; + private ConcurrentHashMap m_buckets = new ConcurrentHashMap(); + private Set m_factoryBuckets = Collections.synchronizedSet( + Collections.newSetFromMap(new IdentityHashMap())); + private File m_baseDir; private String m_localIp = NetworkInterfaceManager.INSTANCE.getLocalHostAddress(); @@ -99,6 +98,8 @@ public class LocalMessageBucketManager extends ContainerHolder @Override public void archive(long startTime) { + ensureInitialized(); + String path = m_pathBuilder.getLogviewPath(new Date(startTime), ""); List keys = new ArrayList(); @@ -121,36 +122,50 @@ public void archive(long startTime) { } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - public List findCloseBuckets() { + ensureInitialized(); + final Set paths = new HashSet(); - Scanners.forDir().scan(m_baseDir, new FileMatcher() { - @Override - public Direction matches(File base, String path) { - if (new File(base, path).isFile()) { - if (shouldUpload(path)) { - int index = path.indexOf(".idx"); + for (String path : listRelativeFiles(m_baseDir)) { + if (shouldUpload(path)) { + int index = path.indexOf(".idx"); - if (index == -1) { - paths.add(path); - } else { - paths.add(path.substring(0, index)); - } - } + if (index == -1) { + paths.add(path); + } else { + paths.add(path.substring(0, index)); } - return Direction.DOWN; } - }); + } return new ArrayList(paths); } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + private volatile boolean m_initialized; + + public synchronized void initialize() { + if (m_initialized) { + return; + } + if (m_configManager == null) { + throw new IllegalStateException("ServerConfigManager is required for local message bucket manager."); + } + if (m_serverStateManager == null) { + throw new IllegalStateException("ServerStatisticManager is required for local message bucket manager."); + } + if (m_pathBuilder == null) { + throw new IllegalStateException("PathBuilder is required for local message bucket manager."); + } + if (m_bucketFactory == null) { + throw new IllegalStateException("MessageBucketFactory is required for local message bucket manager."); + } + if (!m_configManager.isUseNewStorage()) { m_baseDir = new File(m_configManager.getHdfsLocalBaseDir(ServerConfigManager.DUMP_DIR)); @@ -169,10 +184,13 @@ public void initialize() throws InitializationException { } m_last = m_messageQueues.get(m_gzipThreads - 1); } + m_initialized = true; } @Override public MessageTree loadMessage(String messageId) { + ensureInitialized(); + Transaction t = Cat.newTransaction("BucketService", getClass().getSimpleName()); t.setStatus(Message.SUCCESS); @@ -184,15 +202,11 @@ public MessageTree loadMessage(String messageId) { final String key = id.getDomain() + '-' + id.getIpAddress(); final List paths = new ArrayList(); - Scanners.forDir().scan(dir, new FileMatcher() { - @Override - public Direction matches(File base, String name) { - if (name.contains(key) && !name.endsWith(".idx")) { - paths.add(path + name); - } - return Direction.NEXT; + for (String name : listRelativeFiles(dir)) { + if (name.contains(key) && !name.endsWith(".idx")) { + paths.add(path + name); } - }); + } for (String dataFile : paths) { LocalMessageBucket bucket = m_buckets.get(dataFile); @@ -226,9 +240,7 @@ public Direction matches(File base, String name) { if (file.exists()) { try { - bucket = (LocalMessageBucket) lookup(MessageBucket.class, LocalMessageBucket.ID); - bucket.setBaseDir(m_baseDir); - bucket.initialize(dataFile); + bucket = createBucket(dataFile); MessageTree tree = bucket.findById(messageId); @@ -239,8 +251,10 @@ public Direction matches(File base, String name) { } catch (Exception e) { Cat.logError(e); } finally { - bucket.close(); - release(bucket); + if (bucket != null) { + bucket.close(); + releaseBucket(bucket); + } } } } @@ -265,14 +279,51 @@ private void logStorageState(final MessageTree tree) { } } + private List listRelativeFiles(File baseFile) { + List paths = new ArrayList(); + + if (baseFile == null || !baseFile.exists()) { + return paths; + } + + try (Stream stream = Files.walk(baseFile.toPath())) { + stream.filter(Files::isRegularFile) + .map(path -> relativePath(baseFile, path)) + .forEach(paths::add); + } catch (IOException e) { + Cat.logError(e); + } + return paths; + } + + private String relativePath(File baseFile, Path path) { + return baseFile.toPath().relativize(path).toString().replace(File.separatorChar, '/'); + } + public void setBaseDir(File baseDir) { m_baseDir = baseDir; } + public void setBucketFactory(MessageBucketFactory bucketFactory) { + m_bucketFactory = bucketFactory; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + public void setLocalIp(String localIp) { m_localIp = localIp; } + public void setPathBuilder(PathBuilder pathBuilder) { + m_pathBuilder = pathBuilder; + } + + public void setServerStateManager(ServerStatisticManager serverStateManager) { + m_serverStateManager = serverStateManager; + } + private boolean shouldUpload(String path) { long current = System.currentTimeMillis(); long currentHour = current - current % TimeHelper.ONE_HOUR; @@ -295,6 +346,8 @@ private boolean shouldUpload(String path) { @Override public void storeMessage(final MessageTree tree, final MessageId id) { + ensureInitialized(); + boolean errorFlag = true; int hash = Math.abs((id.getDomain() + '-' + id.getIpAddress()).hashCode()); int index = (int) (hash % m_gzipThreads); @@ -332,7 +385,7 @@ private void closeBuckets(final List paths) { Cat.logError(e); } finally { m_buckets.remove(path); - release(bucket); + releaseBucket(bucket); } } } @@ -396,9 +449,7 @@ private void gzipMessage(MessageItem item) { synchronized (m_buckets) { bucket = m_buckets.get(path); if (bucket == null) { - bucket = (LocalMessageBucket) lookup(MessageBucket.class, LocalMessageBucket.ID); - bucket.setBaseDir(m_baseDir); - bucket.initialize(path); + bucket = createBucket(path); m_buckets.put(path, bucket); } @@ -453,4 +504,22 @@ public void shutdown() { } } + private LocalMessageBucket createBucket(String dataFile) throws Exception { + if (m_bucketFactory == null) { + throw new IllegalStateException("MessageBucketFactory is required for local message storage."); + } + LocalMessageBucket bucket = m_bucketFactory.createBucket(m_baseDir, dataFile); + + m_factoryBuckets.add(bucket); + return bucket; + } + + private void releaseBucket(LocalMessageBucket bucket) { + if (m_factoryBuckets.remove(bucket)) { + SLF4J_LOGGER.debug("Closed Spring-created local message storage bucket, bucket={}.", bucket); + } else { + SLF4J_LOGGER.debug("Closed externally-created local message storage bucket, bucket={}.", bucket); + } + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventAnalyzer.java index a153118047..bf7373de15 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventAnalyzer.java @@ -21,8 +21,10 @@ import com.dianping.cat.Cat; import com.dianping.cat.CatConstants; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.event.model.entity.*; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.message.Event; @@ -30,40 +32,40 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Threads; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import com.dianping.cat.support.Threads; import java.util.List; import java.util.Set; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = EventAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class EventAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + EventAnalyzer.ID) +@Scope("prototype") +public class EventAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "event"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = EventAnalyzer.ID + "ReportManager") + private ReportManager eventReportManager; - @Inject - private AtomicMessageConfigManager m_atomicMessageConfigManager; + @Resource(name = "atomicMessageConfigManager") + private AtomicMessageConfigManager atomicMessageConfigManager; - private final EventTpsStatisticsComputer m_computer = new EventTpsStatisticsComputer(); + private final EventTpsStatisticsComputer eventTpsStatisticsComputer = new EventTpsStatisticsComputer(); - private int m_typeCountLimit = 100; + private int typeCountLimit = 100; - private static final int m_statusCodeCountLimit = 100; + private static final int statusCodeCountLimit = 100; - private long m_nextClearTime; + private long nextClearTime; @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + eventReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + eventReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } @@ -73,12 +75,12 @@ public EventReport getReport(String domain) { long timestamp = System.currentTimeMillis(); long remainder = timestamp % 3600000; long current = timestamp - remainder; - EventReport report = m_reportManager.getHourlyReport(period, domain, false); + EventReport report = eventReportManager.getHourlyReport(period, domain, false); if (period == current) { - report.accept(m_computer.setDuration(remainder / 1000.0)); + report.accept(eventTpsStatisticsComputer.setDuration(remainder / 1000.0)); } else if (period < current) { - report.accept(m_computer.setDuration(3600)); + report.accept(eventTpsStatisticsComputer.setDuration(3600)); } // report.getIps().addAll(report.getMachines().keySet()); @@ -86,18 +88,13 @@ public EventReport getReport(String domain) { return report; } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - private EventType findOrCreateType(Machine machine, String type) { EventType eventType = machine.findType(type); if (eventType == null) { int size = machine.getTypes().size(); - if (size > m_typeCountLimit) { + if (size > typeCountLimit) { eventType = machine.findOrCreateType(CatConstants.OTHERS); } else { eventType = machine.findOrCreateType(type); @@ -113,7 +110,7 @@ private EventName findOrCreateName(EventType type, String name, String domain) { if (eventName == null) { int size = type.getNames().size(); - if (size > m_atomicMessageConfigManager.getMaxNameThreshold(domain)) { + if (size > atomicMessageConfigManager.getMaxNameThreshold(domain)) { eventName = type.findOrCreateName(CatConstants.OTHERS); } else { eventName = type.findOrCreateName(name); @@ -129,7 +126,7 @@ private StatusCode findOrCreateStatusCode(EventName name, String codeName) { if (code == null) { int size = name.getStatusCodes().size(); - if (size > m_statusCodeCountLimit) { + if (size > statusCodeCountLimit) { code = name.findOrCreateStatusCode(CatConstants.OTHERS); } else { code = name.findOrCreateStatusCode(codeName); @@ -143,7 +140,7 @@ private void cleanUpReports() { Transaction t = Cat.newTransaction("CleanUpEventReports", minute); try { - Set domains = m_reportManager.getDomains(m_startTime); + Set domains = eventReportManager.getDomains(m_startTime); for (String domain : domains) { Transaction tran = Cat.newTransaction("CleanUpEvent", minute); @@ -151,16 +148,16 @@ private void cleanUpReports() { tran.addData("domain", domain); EventReportCountFilter visitor = new EventReportCountFilter(m_serverConfigManager.getMaxTypeThreshold(), - m_atomicMessageConfigManager.getMaxNameThreshold(domain), m_serverConfigManager.getTypeNameLengthLimit()); + atomicMessageConfigManager.getMaxNameThreshold(domain), m_serverConfigManager.getTypeNameLengthLimit()); try { - EventReport report = m_reportManager.getHourlyReport(m_startTime, domain, false); + EventReport report = eventReportManager.getHourlyReport(m_startTime, domain, false); visitor.visitEventReport(report); tran.success(); } catch (Exception e) { try { - EventReport report = m_reportManager.getHourlyReport(m_startTime, domain, false); + EventReport report = eventReportManager.getHourlyReport(m_startTime, domain, false); visitor.visitEventReport(report); tran.success(); @@ -190,25 +187,35 @@ private String formatStatus(String status) { @Override public ReportManager getReportManager() { - return m_reportManager; + return eventReportManager; } public void setReportManager(ReportManager reportManager) { - m_reportManager = reportManager; + eventReportManager = reportManager; + } + + public void setAtomicMessageConfigManager(AtomicMessageConfigManager atomicMessageConfigManager) { + this.atomicMessageConfigManager = atomicMessageConfigManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); } @Override public void initialize(long startTime, long duration, long extraTime) { super.initialize(startTime, duration, extraTime); - m_typeCountLimit = m_serverConfigManager.getMaxTypeThreshold(); + typeCountLimit = m_serverConfigManager.getMaxTypeThreshold(); final long current = System.currentTimeMillis(); if (startTime < current) { - m_nextClearTime = TimeHelper.getCurrentMinute().getTime() + TimeHelper.ONE_MINUTE * 2; + nextClearTime = TimeHelper.getCurrentMinute().getTime() + TimeHelper.ONE_MINUTE * 2; } else { - m_nextClearTime = startTime + TimeHelper.ONE_MINUTE * 2; + nextClearTime = startTime + TimeHelper.ONE_MINUTE * 2; } } @@ -225,14 +232,14 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + eventReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override public void process(MessageTree tree) { String domain = tree.getDomain(); String ip = tree.getIpAddress(); - EventReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + EventReport report = eventReportManager.getHourlyReport(getStartTime(), domain, true); List events = tree.findOrCreateEvents(); for (Event event : events) { @@ -254,8 +261,8 @@ public void process(MessageTree tree) { processEvent(report, tree, event, ip, total, fail, batchData); } - if (System.currentTimeMillis() > m_nextClearTime) { - m_nextClearTime = m_nextClearTime + TimeHelper.ONE_MINUTE; + if (System.currentTimeMillis() > nextClearTime) { + nextClearTime = nextClearTime + TimeHelper.ONE_MINUTE; Threads.forGroup("cat").start(new Runnable() { diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventDelegate.java index 84fd4fe589..61e5f50436 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/EventDelegate.java @@ -31,28 +31,20 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = EventAnalyzer.ID) public class EventDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_configManager; - @Inject private AllReportConfigManager m_allManager; - @Inject private ServerConfigManager m_serverConfigManager; - @Inject private AtomicMessageConfigManager m_atomicMessageConfigManager; private final EventTpsStatisticsComputer m_computer = new EventTpsStatisticsComputer(); @@ -154,4 +146,24 @@ public EventReport parseBinary(byte[] bytes) { public EventReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager configManager) { + m_configManager = configManager; + } + + public void setAllManager(AllReportConfigManager allManager) { + m_allManager = allManager; + } + + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; + } + + public void setAtomicMessageConfigManager(AtomicMessageConfigManager atomicMessageConfigManager) { + m_atomicMessageConfigManager = atomicMessageConfigManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/BaseEntity.java new file mode 100644 index 0000000000..2c9b45dd14 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.event.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.event.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/Constants.java new file mode 100644 index 0000000000..7979c5990b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/Constants.java @@ -0,0 +1,66 @@ +package com.dianping.cat.consumer.event.model; + +public class Constants { + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_DURATION = "duration"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_FAILCOUNT = "failCount"; + + public static final String ATTR_FAILPERCENT = "failPercent"; + + public static final String ATTR_FAILS = "fails"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_TOTALCOUNT = "totalCount"; + + public static final String ATTR_TPS = "tps"; + + public static final String ATTR_VALUE = "value"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ELEMENT_FAILMESSAGEURL = "failMessageUrl"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ELEMENT_SUCCESSMESSAGEURL = "successMessageUrl"; + + public static final String ENTITY_EVENT_REPORT = "event-report"; + + public static final String ENTITY_GRAPH_TREND = "graph-trend"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_NAME = "name"; + + public static final String ENTITY_NAMES = "names"; + + public static final String ENTITY_RANGE = "range"; + + public static final String ENTITY_RANGES = "ranges"; + + public static final String ENTITY_STATUSCODE = "statusCode"; + + public static final String ENTITY_STATUSCODES = "statusCodes"; + + public static final String ENTITY_TYPE = "type"; + + public static final String ENTITY_TYPES = "types"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IEntity.java new file mode 100644 index 0000000000..0dfbbff04e --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.event.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IVisitor.java new file mode 100644 index 0000000000..6998990c6a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/IVisitor.java @@ -0,0 +1,26 @@ +package com.dianping.cat.consumer.event.model; + +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public interface IVisitor { + + public void visitEventReport(EventReport eventReport); + + public void visitGraphTrend(GraphTrend graphTrend); + + public void visitMachine(Machine machine); + + public void visitName(EventName name); + + public void visitRange(Range range); + + public void visitStatusCode(StatusCode statusCode); + + public void visitType(EventType type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventName.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventName.java new file mode 100644 index 0000000000..706a2f76ac --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventName.java @@ -0,0 +1,255 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_NAME; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class EventName extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private long m_failCount; + + private double m_failPercent; + + private String m_successMessageUrl; + + private String m_failMessageUrl; + + private Map m_ranges = new ConcurrentHashMap(); + + private double m_tps; + + private transient double m_totalPercent; + + private GraphTrend m_graphTrend; + + private Map m_statusCodes = new ConcurrentHashMap(); + + public EventName() { + } + + public EventName(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitName(this); + } + + public EventName addRange(Range range) { + m_ranges.put(range.getValue(), range); + return this; + } + + public EventName addStatusCode(StatusCode statusCode) { + m_statusCodes.put(statusCode.getId(), statusCode); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EventName) { + EventName _o = (EventName) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Range findRange(Integer value) { + return m_ranges.get(value); + } + + public StatusCode findStatusCode(String id) { + return m_statusCodes.get(id); + } + + public Range findOrCreateRange(Integer value) { + Range range = m_ranges.get(value); + + if (range == null) { + synchronized (m_ranges) { + range = m_ranges.get(value); + + if (range == null) { + range = new Range(value); + m_ranges.put(value, range); + } + } + } + + return range; + } + + public StatusCode findOrCreateStatusCode(String id) { + StatusCode statusCode = m_statusCodes.get(id); + + if (statusCode == null) { + synchronized (m_statusCodes) { + statusCode = m_statusCodes.get(id); + + if (statusCode == null) { + statusCode = new StatusCode(id); + m_statusCodes.put(id, statusCode); + } + } + } + + return statusCode; + } + + public long getFailCount() { + return m_failCount; + } + + public String getFailMessageUrl() { + return m_failMessageUrl; + } + + public double getFailPercent() { + return m_failPercent; + } + + public GraphTrend getGraphTrend() { + return m_graphTrend; + } + + public String getId() { + return m_id; + } + + public Map getRanges() { + return m_ranges; + } + + public Map getStatusCodes() { + return m_statusCodes; + } + + public String getSuccessMessageUrl() { + return m_successMessageUrl; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTotalPercent() { + return m_totalPercent; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public EventName incFailCount() { + m_failCount++; + return this; + } + + public EventName incFailCount(long failCount) { + m_failCount += failCount; + return this; + } + + public EventName incTotalCount() { + m_totalCount++; + return this; + } + + public EventName incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(EventName other) { + assertAttributeEquals(other, ENTITY_NAME, ATTR_ID, m_id, other.getId()); + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_tps = other.getTps(); + + m_totalPercent = other.getTotalPercent(); + } + + public Range removeRange(Integer value) { + return m_ranges.remove(value); + } + + public StatusCode removeStatusCode(String id) { + return m_statusCodes.remove(id); + } + + public EventName setFailCount(long failCount) { + m_failCount = failCount; + return this; + } + + public EventName setFailMessageUrl(String failMessageUrl) { + m_failMessageUrl = failMessageUrl; + return this; + } + + public EventName setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public EventName setGraphTrend(GraphTrend graphTrend) { + m_graphTrend = graphTrend; + return this; + } + + public EventName setId(String id) { + m_id = id; + return this; + } + + public EventName setSuccessMessageUrl(String successMessageUrl) { + m_successMessageUrl = successMessageUrl; + return this; + } + + public EventName setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public EventName setTotalPercent(double totalPercent) { + m_totalPercent = totalPercent; + return this; + } + + public EventName setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventReport.java new file mode 100644 index 0000000000..ed3c733f19 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventReport.java @@ -0,0 +1,155 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_EVENT_REPORT; + +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class EventReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Set m_domainNames = new LinkedHashSet(); + + private Map m_machines = new ConcurrentHashMap(); + + private Set m_ips = new LinkedHashSet(); + + public EventReport() { + } + + public EventReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitEventReport(this); + } + + public EventReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public EventReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public EventReport addMachine(Machine machine) { + m_machines.put(machine.getIp(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EventReport) { + EventReport _o = (EventReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String ip) { + return m_machines.get(ip); + } + + public Machine findOrCreateMachine(String ip) { + Machine machine = m_machines.get(ip); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(ip); + + if (machine == null) { + machine = new Machine(ip); + m_machines.put(ip, machine); + } + } + } + + return machine; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Set getIps() { + return m_ips; + } + + public Map getMachines() { + return m_machines; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(EventReport other) { + assertAttributeEquals(other, ENTITY_EVENT_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String ip) { + return m_machines.remove(ip); + } + + public EventReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public EventReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public EventReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventType.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventType.java new file mode 100644 index 0000000000..0ed661f7b0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/EventType.java @@ -0,0 +1,206 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_TYPE; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class EventType extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private long m_failCount; + + private double m_failPercent; + + private String m_successMessageUrl; + + private String m_failMessageUrl; + + private Map m_names = new ConcurrentHashMap(); + + private double m_tps; + + private GraphTrend m_graphTrend; + + public EventType() { + } + + public EventType(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitType(this); + } + + public EventType addName(EventName name) { + m_names.put(name.getId(), name); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EventType) { + EventType _o = (EventType) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public EventName findName(String id) { + return m_names.get(id); + } + + public EventName findOrCreateName(String id) { + EventName name = m_names.get(id); + + if (name == null) { + synchronized (m_names) { + name = m_names.get(id); + + if (name == null) { + name = new EventName(id); + m_names.put(id, name); + } + } + } + + return name; + } + + public long getFailCount() { + return m_failCount; + } + + public String getFailMessageUrl() { + return m_failMessageUrl; + } + + public double getFailPercent() { + return m_failPercent; + } + + public GraphTrend getGraphTrend() { + return m_graphTrend; + } + + public String getId() { + return m_id; + } + + public Map getNames() { + return m_names; + } + + public String getSuccessMessageUrl() { + return m_successMessageUrl; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public EventType incFailCount() { + m_failCount++; + return this; + } + + public EventType incFailCount(long failCount) { + m_failCount += failCount; + return this; + } + + public EventType incTotalCount() { + m_totalCount++; + return this; + } + + public EventType incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(EventType other) { + assertAttributeEquals(other, ENTITY_TYPE, ATTR_ID, m_id, other.getId()); + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_tps = other.getTps(); + } + + public EventName removeName(String id) { + return m_names.remove(id); + } + + public EventType setFailCount(long failCount) { + m_failCount = failCount; + return this; + } + + public EventType setFailMessageUrl(String failMessageUrl) { + m_failMessageUrl = failMessageUrl; + return this; + } + + public EventType setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public EventType setGraphTrend(GraphTrend graphTrend) { + m_graphTrend = graphTrend; + return this; + } + + public EventType setId(String id) { + m_id = id; + return this; + } + + public EventType setSuccessMessageUrl(String successMessageUrl) { + m_successMessageUrl = successMessageUrl; + return this; + } + + public EventType setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public EventType setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/GraphTrend.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/GraphTrend.java new file mode 100644 index 0000000000..4c39b64ead --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/GraphTrend.java @@ -0,0 +1,88 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_GRAPH_TREND; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class GraphTrend extends BaseEntity { + private int m_duration; + + private String m_count = ""; + + private String m_fails = ""; + + public GraphTrend() { + } + + public GraphTrend(int duration) { + m_duration = duration; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGraphTrend(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof GraphTrend) { + GraphTrend _o = (GraphTrend) obj; + + if (getDuration() != _o.getDuration()) { + return false; + } + + return true; + } + + return false; + } + + public String getCount() { + return m_count; + } + + public int getDuration() { + return m_duration; + } + + public String getFails() { + return m_fails; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_duration; + + return hash; + } + + @Override + public void mergeAttributes(GraphTrend other) { + assertAttributeEquals(other, ENTITY_GRAPH_TREND, ATTR_DURATION, m_duration, other.getDuration()); + + m_count = other.getCount(); + + m_fails = other.getFails(); + } + + public GraphTrend setCount(String count) { + m_count = count; + return this; + } + + public GraphTrend setDuration(int duration) { + m_duration = duration; + return this; + } + + public GraphTrend setFails(String fails) { + m_fails = fails; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Machine.java new file mode 100644 index 0000000000..4d0cbf7918 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Machine.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_MACHINE; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_ip; + + private Map m_types = new ConcurrentHashMap(); + + public Machine() { + } + + public Machine(String ip) { + m_ip = ip; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addType(EventType type) { + m_types.put(type.getId(), type); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getIp(), _o.getIp())) { + return false; + } + + return true; + } + + return false; + } + + public EventType findType(String id) { + return m_types.get(id); + } + + public EventType findOrCreateType(String id) { + EventType type = m_types.get(id); + + if (type == null) { + synchronized (m_types) { + type = m_types.get(id); + + if (type == null) { + type = new EventType(id); + m_types.put(id, type); + } + } + } + + return type; + } + + public String getIp() { + return m_ip; + } + + public Map getTypes() { + return m_types; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_ip == null ? 0 : m_ip.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_IP, m_ip, other.getIp()); + + } + + public EventType removeType(String id) { + return m_types.remove(id); + } + + public Machine setIp(String ip) { + m_ip = ip; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Range.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Range.java new file mode 100644 index 0000000000..428236f74e --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/Range.java @@ -0,0 +1,108 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_RANGE; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class Range extends BaseEntity { + private Integer m_value; + + private int m_count; + + private int m_fails; + + public Range() { + } + + public Range(Integer value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRange(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Range) { + Range _o = (Range) obj; + + if (!equals(getValue(), _o.getValue())) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public int getFails() { + return m_fails; + } + + public Integer getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_value == null ? 0 : m_value.hashCode()); + + return hash; + } + + public Range incCount() { + m_count++; + return this; + } + + public Range incCount(int count) { + m_count += count; + return this; + } + + public Range incFails() { + m_fails++; + return this; + } + + public Range incFails(int fails) { + m_fails += fails; + return this; + } + + @Override + public void mergeAttributes(Range other) { + assertAttributeEquals(other, ENTITY_RANGE, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + + m_fails = other.getFails(); + } + + public Range setCount(int count) { + m_count = count; + return this; + } + + public Range setFails(int fails) { + m_fails = fails; + return this; + } + + public Range setValue(Integer value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/StatusCode.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/StatusCode.java new file mode 100644 index 0000000000..c5f34369ec --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/entity/StatusCode.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.event.model.entity; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_STATUSCODE; + +import com.dianping.cat.consumer.event.model.BaseEntity; +import com.dianping.cat.consumer.event.model.IVisitor; + +public class StatusCode extends BaseEntity { + private String m_id; + + private long m_count; + + public StatusCode() { + } + + public StatusCode(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitStatusCode(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StatusCode) { + StatusCode _o = (StatusCode) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public long getCount() { + return m_count; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public StatusCode incCount() { + m_count++; + return this; + } + + public StatusCode incCount(long count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(StatusCode other) { + assertAttributeEquals(other, ENTITY_STATUSCODE, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + } + + public StatusCode setCount(long count) { + m_count = count; + return this; + } + + public StatusCode setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..d53cf8e53c --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/BaseVisitor.java @@ -0,0 +1,64 @@ +package com.dianping.cat.consumer.event.model.transform; + +import com.dianping.cat.consumer.event.model.IVisitor; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitEventReport(EventReport eventReport) { + for (Machine machine : eventReport.getMachines().values()) { + visitMachine(machine); + } + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + } + + @Override + public void visitMachine(Machine machine) { + for (EventType type : machine.getTypes().values()) { + visitType(type); + } + } + + @Override + public void visitName(EventName name) { + for (Range range : name.getRanges().values()) { + visitRange(range); + } + + if (name.getGraphTrend() != null) { + visitGraphTrend(name.getGraphTrend()); + } + + for (StatusCode statusCode : name.getStatusCodes().values()) { + visitStatusCode(statusCode); + } + } + + @Override + public void visitRange(Range range) { + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + } + + @Override + public void visitType(EventType type) { + for (EventName name : type.getNames().values()) { + visitName(name); + } + + if (type.getGraphTrend() != null) { + visitGraphTrend(type.getGraphTrend()); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..76045d20ea --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultLinker.java @@ -0,0 +1,119 @@ +package com.dianping.cat.consumer.event.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onGraphTrend(final EventType parent, final GraphTrend graphTrend) { + parent.setGraphTrend(graphTrend); + return true; + } + + @Override + public boolean onGraphTrend(final EventName parent, final GraphTrend graphTrend) { + parent.setGraphTrend(graphTrend); + return true; + } + + @Override + public boolean onMachine(final EventReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onName(final EventType parent, final EventName name) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addName(name); + } + }); + } else { + parent.addName(name); + } + + return true; + } + + @Override + public boolean onRange(final EventName parent, final Range range) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRange(range); + } + }); + } else { + parent.addRange(range); + } + + return true; + } + + @Override + public boolean onStatusCode(final EventName parent, final StatusCode statusCode) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addStatusCode(statusCode); + } + }); + } else { + parent.addStatusCode(statusCode); + } + + return true; + } + + @Override + public boolean onType(final Machine parent, final EventType type) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addType(type); + } + }); + } else { + parent.addType(type); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..e77b6232e3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultMerger.java @@ -0,0 +1,244 @@ +package com.dianping.cat.consumer.event.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.event.model.IEntity; +import com.dianping.cat.consumer.event.model.IVisitor; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; +import com.dianping.cat.consumer.event.model.entity.EventType; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private EventReport m_eventReport; + + public DefaultMerger() { + } + + public DefaultMerger(EventReport eventReport) { + m_eventReport = eventReport; + m_objs.push(eventReport); + } + + public EventReport getEventReport() { + return m_eventReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeEventReport(EventReport to, EventReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + to.getIps().addAll(from.getIps()); + } + + protected void mergeGraphTrend(GraphTrend to, GraphTrend from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeName(EventName to, EventName from) { + to.mergeAttributes(from); + to.setSuccessMessageUrl(from.getSuccessMessageUrl()); + to.setFailMessageUrl(from.getFailMessageUrl()); + } + + protected void mergeRange(Range to, Range from) { + to.mergeAttributes(from); + } + + protected void mergeStatusCode(StatusCode to, StatusCode from) { + to.mergeAttributes(from); + } + + protected void mergeType(EventType to, EventType from) { + to.mergeAttributes(from); + to.setSuccessMessageUrl(from.getSuccessMessageUrl()); + to.setFailMessageUrl(from.getFailMessageUrl()); + } + + @Override + public void visitEventReport(EventReport from) { + EventReport to = (EventReport) m_objs.peek(); + + mergeEventReport(to, from); + visitEventReportChildren(to, from); + } + + protected void visitEventReportChildren(EventReport to, EventReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getIp()); + + if (target == null) { + target = new Machine(source.getIp()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitGraphTrend(GraphTrend from) { + GraphTrend to = (GraphTrend) m_objs.peek(); + + mergeGraphTrend(to, from); + visitGraphTrendChildren(to, from); + } + + protected void visitGraphTrendChildren(GraphTrend to, GraphTrend from) { + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (EventType source : from.getTypes().values()) { + EventType target = to.findType(source.getId()); + + if (target == null) { + target = new EventType(source.getId()); + to.addType(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitName(EventName from) { + EventName to = (EventName) m_objs.peek(); + + mergeName(to, from); + visitNameChildren(to, from); + } + + protected void visitNameChildren(EventName to, EventName from) { + for (Range source : from.getRanges().values()) { + Range target = to.findRange(source.getValue()); + + if (target == null) { + target = new Range(source.getValue()); + to.addRange(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getGraphTrend() != null) { + GraphTrend target = to.getGraphTrend(); + + if (target == null) { + GraphTrend source = from.getGraphTrend(); + + target = new GraphTrend(source.getDuration()); + to.setGraphTrend(target); + } + + m_objs.push(target); + from.getGraphTrend().accept(this); + m_objs.pop(); + } + + for (StatusCode source : from.getStatusCodes().values()) { + StatusCode target = to.findStatusCode(source.getId()); + + if (target == null) { + target = new StatusCode(source.getId()); + to.addStatusCode(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitRange(Range from) { + Range to = (Range) m_objs.peek(); + + mergeRange(to, from); + visitRangeChildren(to, from); + } + + protected void visitRangeChildren(Range to, Range from) { + } + + @Override + public void visitStatusCode(StatusCode from) { + StatusCode to = (StatusCode) m_objs.peek(); + + mergeStatusCode(to, from); + visitStatusCodeChildren(to, from); + } + + protected void visitStatusCodeChildren(StatusCode to, StatusCode from) { + } + + @Override + public void visitType(EventType from) { + EventType to = (EventType) m_objs.peek(); + + mergeType(to, from); + visitTypeChildren(to, from); + } + + protected void visitTypeChildren(EventType to, EventType from) { + for (EventName source : from.getNames().values()) { + EventName target = to.findName(source.getId()); + + if (target == null) { + target = new EventName(source.getId()); + to.addName(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getGraphTrend() != null) { + GraphTrend target = to.getGraphTrend(); + + if (target == null) { + GraphTrend source = from.getGraphTrend(); + + target = new GraphTrend(source.getDuration()); + to.setGraphTrend(target); + } + + m_objs.push(target); + from.getGraphTrend().accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..9452d906b3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,314 @@ +package com.dianping.cat.consumer.event.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.event.model.IVisitor; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(EventReport eventReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(eventReport, out); + return out.toByteArray(); + } + + public static void build(EventReport eventReport, OutputStream out) { + eventReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitEventReport(EventReport eventReport) { + writeTag(63, 0); + + if (eventReport.getDomain() != null) { + writeTag(1, 1); + writeString(eventReport.getDomain()); + } + + if (eventReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(eventReport.getStartTime()); + } + + if (eventReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(eventReport.getEndTime()); + } + + if (eventReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(eventReport.getDomainNames().size()); + + for (String domain : eventReport.getDomainNames()) { + writeString(domain); + } + } + + if (eventReport.getIps() != null) { + writeTag(5, 2); + writeInt(eventReport.getIps().size()); + + for (String ip : eventReport.getIps()) { + writeString(ip); + } + } + + if (!eventReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(eventReport.getMachines().size()); + + for (Machine machine : eventReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + writeTag(1, 0); + writeInt(graphTrend.getDuration()); + + writeTag(2, 0); + writeString(graphTrend.getCount()); + + writeTag(3, 0); + writeString(graphTrend.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getIp() != null) { + writeTag(1, 1); + writeString(machine.getIp()); + } + + if (!machine.getTypes().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getTypes().size()); + + for (EventType type : machine.getTypes().values()) { + type.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitName(EventName name) { + if (name.getId() != null) { + writeTag(1, 1); + writeString(name.getId()); + } + + writeTag(2, 0); + writeLong(name.getTotalCount()); + + writeTag(3, 0); + writeLong(name.getFailCount()); + + writeTag(4, 0); + writeDouble(name.getFailPercent()); + + if (name.getSuccessMessageUrl() != null) { + writeTag(5, 1); + writeString(name.getSuccessMessageUrl()); + } + + if (name.getFailMessageUrl() != null) { + writeTag(6, 1); + writeString(name.getFailMessageUrl()); + } + + writeTag(7, 0); + writeDouble(name.getTps()); + + if (!name.getRanges().isEmpty()) { + writeTag(33, 2); + writeInt(name.getRanges().size()); + + for (Range range : name.getRanges().values()) { + range.accept(m_visitor); + } + } + + if (name.getGraphTrend() != null) { + writeTag(34, 1); + name.getGraphTrend().accept(m_visitor); + } + + if (!name.getStatusCodes().isEmpty()) { + writeTag(35, 2); + writeInt(name.getStatusCodes().size()); + + for (StatusCode statusCode : name.getStatusCodes().values()) { + statusCode.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitRange(Range range) { + if (range.getValue() != null) { + writeTag(1, 1); + writeInt(range.getValue()); + } + + writeTag(2, 0); + writeInt(range.getCount()); + + writeTag(3, 0); + writeInt(range.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + if (statusCode.getId() != null) { + writeTag(1, 1); + writeString(statusCode.getId()); + } + + writeTag(2, 0); + writeLong(statusCode.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitType(EventType type) { + if (type.getId() != null) { + writeTag(1, 1); + writeString(type.getId()); + } + + writeTag(2, 0); + writeLong(type.getTotalCount()); + + writeTag(3, 0); + writeLong(type.getFailCount()); + + writeTag(4, 0); + writeDouble(type.getFailPercent()); + + if (type.getSuccessMessageUrl() != null) { + writeTag(5, 1); + writeString(type.getSuccessMessageUrl()); + } + + if (type.getFailMessageUrl() != null) { + writeTag(6, 1); + writeString(type.getFailMessageUrl()); + } + + writeTag(7, 0); + writeDouble(type.getTps()); + + if (!type.getNames().isEmpty()) { + writeTag(33, 2); + writeInt(type.getNames().size()); + + for (EventName name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + if (type.getGraphTrend() != null) { + writeTag(34, 1); + type.getGraphTrend().accept(m_visitor); + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..a45bbd47bc --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultNativeParser.java @@ -0,0 +1,397 @@ +package com.dianping.cat.consumer.event.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.event.model.IVisitor; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static EventReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static EventReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + EventReport eventReport = new EventReport(); + + try { + eventReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return eventReport; + } + + @Override + public void visitEventReport(EventReport eventReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitEventReportChildren(eventReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitEventReportChildren(EventReport eventReport, int _field, int _type) { + switch (_field) { + case 1: + eventReport.setDomain(readString()); + break; + case 2: + eventReport.setStartTime(readDate()); + break; + case 3: + eventReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + eventReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + eventReport.addDomain(readString()); + } + } + break; + case 5: + if (_type == 1) { + eventReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + eventReport.addIp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(eventReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(eventReport, machine); + } + } + break; + } + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + byte tag; + + while ((tag = readTag()) != -1) { + visitGraphTrendChildren(graphTrend, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitGraphTrendChildren(GraphTrend graphTrend, int _field, int _type) { + switch (_field) { + case 1: + graphTrend.setDuration(readInt()); + break; + case 2: + graphTrend.setCount(readString()); + break; + case 3: + graphTrend.setFails(readString()); + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setIp(readString()); + break; + case 33: + if (_type == 1) { + EventType type = new EventType(); + + visitType(type); + m_linker.onType(machine, type); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + EventType type = new EventType(); + + visitType(type); + m_linker.onType(machine, type); + } + } + break; + } + } + + @Override + public void visitName(EventName name) { + byte tag; + + while ((tag = readTag()) != -1) { + visitNameChildren(name, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitNameChildren(EventName name, int _field, int _type) { + switch (_field) { + case 1: + name.setId(readString()); + break; + case 2: + name.setTotalCount(readLong()); + break; + case 3: + name.setFailCount(readLong()); + break; + case 4: + name.setFailPercent(readDouble()); + break; + case 5: + name.setSuccessMessageUrl(readString()); + break; + case 6: + name.setFailMessageUrl(readString()); + break; + case 7: + name.setTps(readDouble()); + break; + case 33: + if (_type == 1) { + Range range = new Range(); + + visitRange(range); + m_linker.onRange(name, range); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Range range = new Range(); + + visitRange(range); + m_linker.onRange(name, range); + } + } + break; + case 34: + GraphTrend graphTrend = new GraphTrend(); + + visitGraphTrend(graphTrend); + m_linker.onGraphTrend(name, graphTrend); + break; + case 35: + if (_type == 1) { + StatusCode statusCode = new StatusCode(); + + visitStatusCode(statusCode); + m_linker.onStatusCode(name, statusCode); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + StatusCode statusCode = new StatusCode(); + + visitStatusCode(statusCode); + m_linker.onStatusCode(name, statusCode); + } + } + break; + } + } + + @Override + public void visitRange(Range range) { + byte tag; + + while ((tag = readTag()) != -1) { + visitRangeChildren(range, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitRangeChildren(Range range, int _field, int _type) { + switch (_field) { + case 1: + range.setValue(readInt()); + break; + case 2: + range.setCount(readInt()); + break; + case 3: + range.setFails(readInt()); + break; + } + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + byte tag; + + while ((tag = readTag()) != -1) { + visitStatusCodeChildren(statusCode, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitStatusCodeChildren(StatusCode statusCode, int _field, int _type) { + switch (_field) { + case 1: + statusCode.setId(readString()); + break; + case 2: + statusCode.setCount(readLong()); + break; + } + } + + @Override + public void visitType(EventType type) { + byte tag; + + while ((tag = readTag()) != -1) { + visitTypeChildren(type, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitTypeChildren(EventType type, int _field, int _type) { + switch (_field) { + case 1: + type.setId(readString()); + break; + case 2: + type.setTotalCount(readLong()); + break; + case 3: + type.setFailCount(readLong()); + break; + case 4: + type.setFailPercent(readDouble()); + break; + case 5: + type.setSuccessMessageUrl(readString()); + break; + case 6: + type.setFailMessageUrl(readString()); + break; + case 7: + type.setTps(readDouble()); + break; + case 33: + if (_type == 1) { + EventName name = new EventName(); + + visitName(name); + m_linker.onName(type, name); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + EventName name = new EventName(); + + visitName(name); + m_linker.onName(type, name); + } + } + break; + case 34: + GraphTrend graphTrend = new GraphTrend(); + + visitGraphTrend(graphTrend); + m_linker.onGraphTrend(type, graphTrend); + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..f64e6eb6ea --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxMaker.java @@ -0,0 +1,220 @@ +package com.dianping.cat.consumer.event.model.transform; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_TPS; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_VALUE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultSaxMaker implements IMaker { + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public EventReport buildEventReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + EventReport eventReport = new EventReport(domain); + + if (startTime != null) { + eventReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + eventReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return eventReport; + } + + @Override + public GraphTrend buildGraphTrend(Attributes attributes) { + String duration = attributes.getValue(ATTR_DURATION); + String count = attributes.getValue(ATTR_COUNT); + String fails = attributes.getValue(ATTR_FAILS); + GraphTrend graphTrend = new GraphTrend(duration == null ? 0 : convert(Integer.class, duration, 0)); + + if (count != null) { + graphTrend.setCount(count); + } + + if (fails != null) { + graphTrend.setFails(fails); + } + + return graphTrend; + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String ip = attributes.getValue(ATTR_IP); + Machine machine = new Machine(ip); + + return machine; + } + + @Override + public EventName buildName(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String tps = attributes.getValue(ATTR_TPS); + EventName name = new EventName(id); + + if (totalCount != null) { + name.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + name.setFailCount(convert(Long.class, failCount, 0L)); + } + + if (failPercent != null) { + name.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (tps != null) { + name.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + return name; + } + + @Override + public Range buildRange(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + String fails = attributes.getValue(ATTR_FAILS); + Range range = new Range(value == null ? null : convert(Integer.class, value, null)); + + if (count != null) { + range.setCount(convert(Integer.class, count, 0)); + } + + if (fails != null) { + range.setFails(convert(Integer.class, fails, 0)); + } + + return range; + } + + @Override + public StatusCode buildStatusCode(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + StatusCode statusCode = new StatusCode(id); + + if (count != null) { + statusCode.setCount(convert(Long.class, count, 0L)); + } + + return statusCode; + } + + @Override + public EventType buildType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String tps = attributes.getValue(ATTR_TPS); + EventType type = new EventType(id); + + if (totalCount != null) { + type.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + type.setFailCount(convert(Long.class, failCount, 0L)); + } + + if (failPercent != null) { + type.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (tps != null) { + type.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..cb365a6649 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultSaxParser.java @@ -0,0 +1,395 @@ +package com.dianping.cat.consumer.event.model.transform; + +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_DOMAIN_NAMES; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_FAILMESSAGEURL; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_IPS; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_SUCCESSMESSAGEURL; + +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_EVENT_REPORT; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_RANGE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_STATUSCODE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.event.model.IEntity; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static EventReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(EventReport.class, new InputSource(removeBOM(in))); + } + + public static EventReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(EventReport.class, new InputSource(removeBOM(reader))); + } + + public static EventReport parse(String xml) throws SAXException, IOException { + return parseEntity(EventReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof EventReport) { + EventReport eventReport = (EventReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + eventReport.addDomain(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + eventReport.addIp(getText()); + } + } else if (currentObj instanceof EventType) { + EventType type = (EventType) currentObj; + + if (ELEMENT_SUCCESSMESSAGEURL.equals(currentTag)) { + type.setSuccessMessageUrl(getText()); + } else if (ELEMENT_FAILMESSAGEURL.equals(currentTag)) { + type.setFailMessageUrl(getText()); + } + } else if (currentObj instanceof EventName) { + EventName name = (EventName) currentObj; + + if (ELEMENT_SUCCESSMESSAGEURL.equals(currentTag)) { + name.setSuccessMessageUrl(getText()); + } else if (ELEMENT_FAILMESSAGEURL.equals(currentTag)) { + name.setFailMessageUrl(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForEventReport(EventReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under event-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForGraphTrend(GraphTrend parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_TYPE.equals(qName)) { + EventType type = m_maker.buildType(attributes); + + m_linker.onType(parentObj, type); + m_objs.push(type); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForName(EventName parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_SUCCESSMESSAGEURL.equals(qName) || ELEMENT_FAILMESSAGEURL.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_RANGE.equals(qName)) { + Range range = m_maker.buildRange(attributes); + + m_linker.onRange(parentObj, range); + m_objs.push(range); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_linker.onGraphTrend(parentObj, graphTrend); + m_objs.push(graphTrend); + } else if (ENTITY_STATUSCODE.equals(qName)) { + StatusCode statusCode = m_maker.buildStatusCode(attributes); + + m_linker.onStatusCode(parentObj, statusCode); + m_objs.push(statusCode); + } else { + throw new SAXException(String.format("Element(%s) is not expected under name!", qName)); + } + + m_tags.push(qName); + } + + private void parseForRange(Range parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForStatusCode(StatusCode parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForType(EventType parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_SUCCESSMESSAGEURL.equals(qName) || ELEMENT_FAILMESSAGEURL.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_NAME.equals(qName)) { + EventName name = m_maker.buildName(attributes); + + m_linker.onName(parentObj, name); + m_objs.push(name); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_linker.onGraphTrend(parentObj, graphTrend); + m_objs.push(graphTrend); + } else { + throw new SAXException(String.format("Element(%s) is not expected under type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_EVENT_REPORT.equals(qName)) { + EventReport eventReport = m_maker.buildEventReport(attributes); + + m_entity = eventReport; + m_objs.push(eventReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_TYPE.equals(qName)) { + EventType type = m_maker.buildType(attributes); + + m_entity = type; + m_objs.push(type); + m_tags.push(qName); + } else if (ENTITY_NAME.equals(qName)) { + EventName name = m_maker.buildName(attributes); + + m_entity = name; + m_objs.push(name); + m_tags.push(qName); + } else if (ENTITY_RANGE.equals(qName)) { + Range range = m_maker.buildRange(attributes); + + m_entity = range; + m_objs.push(range); + m_tags.push(qName); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_entity = graphTrend; + m_objs.push(graphTrend); + m_tags.push(qName); + } else if (ENTITY_STATUSCODE.equals(qName)) { + StatusCode statusCode = m_maker.buildStatusCode(attributes); + + m_entity = statusCode; + m_objs.push(statusCode); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof EventReport) { + parseForEventReport((EventReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof EventType) { + parseForType((EventType) parent, tag, qName, attributes); + } else if (parent instanceof EventName) { + parseForName((EventName) parent, tag, qName, attributes); + } else if (parent instanceof Range) { + parseForRange((Range) parent, tag, qName, attributes); + } else if (parent instanceof GraphTrend) { + parseForGraphTrend((GraphTrend) parent, tag, qName, attributes); + } else if (parent instanceof StatusCode) { + parseForStatusCode((StatusCode) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..a74e98f3c8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,380 @@ +package com.dianping.cat.consumer.event.model.transform; + +import static com.dianping.cat.consumer.event.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_TPS; +import static com.dianping.cat.consumer.event.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_FAILMESSAGEURL; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.event.model.Constants.ELEMENT_SUCCESSMESSAGEURL; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_EVENT_REPORT; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_RANGE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_STATUSCODE; +import static com.dianping.cat.consumer.event.model.Constants.ENTITY_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.event.model.IEntity; +import com.dianping.cat.consumer.event.model.IVisitor; +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitEventReport(EventReport eventReport) { + startTag(ENTITY_EVENT_REPORT, null, ATTR_DOMAIN, eventReport.getDomain(), ATTR_STARTTIME, toString(eventReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(eventReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!eventReport.getDomainNames().isEmpty()) { + for (String domain : eventReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!eventReport.getIps().isEmpty()) { + for (String ip : eventReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!eventReport.getMachines().isEmpty()) { + for (Machine machine : eventReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_EVENT_REPORT); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + startTag(ENTITY_GRAPH_TREND, true, null, ATTR_DURATION, graphTrend.getDuration(), ATTR_COUNT, graphTrend.getCount(), ATTR_FAILS, graphTrend.getFails()); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_IP, machine.getIp()); + + if (!machine.getTypes().isEmpty()) { + for (EventType type : machine.getTypes().values()) { + type.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitName(EventName name) { + startTag(ENTITY_NAME, null, ATTR_ID, name.getId(), ATTR_TOTALCOUNT, name.getTotalCount(), ATTR_FAILCOUNT, name.getFailCount(), ATTR_FAILPERCENT, toString(name.getFailPercent(), "0.00"), ATTR_TPS, toString(name.getTps(), "0.00")); + + element(ELEMENT_SUCCESSMESSAGEURL, name.getSuccessMessageUrl(), null, true); + + element(ELEMENT_FAILMESSAGEURL, name.getFailMessageUrl(), null, true); + + if (!name.getRanges().isEmpty()) { + for (Range range : name.getRanges().values()) { + range.accept(m_visitor); + } + } + + if (name.getGraphTrend() != null) { + name.getGraphTrend().accept(m_visitor); + } + + if (!name.getStatusCodes().isEmpty()) { + for (StatusCode statusCode : name.getStatusCodes().values()) { + statusCode.accept(m_visitor); + } + } + + endTag(ENTITY_NAME); + } + + @Override + public void visitRange(Range range) { + startTag(ENTITY_RANGE, true, null, ATTR_VALUE, range.getValue(), ATTR_COUNT, range.getCount(), ATTR_FAILS, range.getFails()); + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + startTag(ENTITY_STATUSCODE, true, null, ATTR_ID, statusCode.getId(), ATTR_COUNT, statusCode.getCount()); + } + + @Override + public void visitType(EventType type) { + startTag(ENTITY_TYPE, null, ATTR_ID, type.getId(), ATTR_TOTALCOUNT, type.getTotalCount(), ATTR_FAILCOUNT, type.getFailCount(), ATTR_FAILPERCENT, toString(type.getFailPercent(), "0.00"), ATTR_TPS, toString(type.getTps(), "0.00")); + + element(ELEMENT_SUCCESSMESSAGEURL, type.getSuccessMessageUrl(), null, true); + + element(ELEMENT_FAILMESSAGEURL, type.getFailMessageUrl(), null, true); + + if (!type.getNames().isEmpty()) { + for (EventName name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + if (type.getGraphTrend() != null) { + type.getGraphTrend().accept(m_visitor); + } + + endTag(ENTITY_TYPE); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/ILinker.java new file mode 100644 index 0000000000..59484884a1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/ILinker.java @@ -0,0 +1,26 @@ +package com.dianping.cat.consumer.event.model.transform; + +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public interface ILinker { + + public boolean onGraphTrend(EventType parent, GraphTrend graphTrend); + + public boolean onGraphTrend(EventName parent, GraphTrend graphTrend); + + public boolean onMachine(EventReport parent, Machine machine); + + public boolean onName(EventType parent, EventName name); + + public boolean onRange(EventName parent, Range range); + + public boolean onStatusCode(EventName parent, StatusCode statusCode); + + public boolean onType(Machine parent, EventType type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IMaker.java new file mode 100644 index 0000000000..eb18afc481 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IMaker.java @@ -0,0 +1,30 @@ +package com.dianping.cat.consumer.event.model.transform; + +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public interface IMaker { + + public String buildDomain(T node); + + public EventReport buildEventReport(T node); + + public GraphTrend buildGraphTrend(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public EventName buildName(T node); + + public Range buildRange(T node); + + public StatusCode buildStatusCode(T node); + + public EventType buildType(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IParser.java new file mode 100644 index 0000000000..5c1f604b21 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/event/model/transform/IParser.java @@ -0,0 +1,25 @@ +package com.dianping.cat.consumer.event.model.transform; + +import com.dianping.cat.consumer.event.model.entity.EventName; +import com.dianping.cat.consumer.event.model.entity.EventReport; +import com.dianping.cat.consumer.event.model.entity.EventType; +import com.dianping.cat.consumer.event.model.entity.GraphTrend; +import com.dianping.cat.consumer.event.model.entity.Machine; +import com.dianping.cat.consumer.event.model.entity.Range; +import com.dianping.cat.consumer.event.model.entity.StatusCode; + +public interface IParser { + public EventReport parse(IMaker maker, ILinker linker, T node); + + public void parseForGraphTrend(IMaker maker, ILinker linker, GraphTrend parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForEventName(IMaker maker, ILinker linker, EventName parent, T node); + + public void parseForRange(IMaker maker, ILinker linker, Range parent, T node); + + public void parseForStatusCode(IMaker maker, ILinker linker, StatusCode parent, T node); + + public void parseForEventType(IMaker maker, ILinker linker, EventType parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzer.java index 35bcd4191f..094294d183 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzer.java @@ -20,7 +20,8 @@ import com.dianping.cat.Cat; import com.dianping.cat.analysis.AbstractMessageAnalyzer; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; import com.dianping.cat.consumer.heartbeat.model.entity.Machine; @@ -31,24 +32,24 @@ import com.dianping.cat.report.ReportManager; import com.dianping.cat.status.model.StatusInfoHelper; import com.dianping.cat.status.model.entity.*; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; import java.util.Map.Entry; -@Named(type = MessageAnalyzer.class, value = HeartbeatAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class HeartbeatAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + HeartbeatAnalyzer.ID) +@Scope("prototype") +public class HeartbeatAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "heartbeat"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = HeartbeatAnalyzer.ID + "ReportManager") + private ReportManager reportManager; - @Inject - private ServerFilterConfigManager m_serverFilterConfigManager; + @Resource(name = "serverFilterConfigManager") + private ServerFilterConfigManager serverFilterConfigManager; private Period buildHeartBeatInfo(Machine machine, Heartbeat heartbeat, long timestamp) { String xml = (String) heartbeat.getData(); @@ -96,25 +97,20 @@ private Period buildHeartBeatInfo(Machine machine, Heartbeat heartbeat, long tim @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public HeartbeatReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, false); + return reportManager.getHourlyReport(getStartTime(), domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return reportManager; } @Override @@ -124,15 +120,15 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override protected void process(MessageTree tree) { String domain = tree.getDomain(); - if (m_serverFilterConfigManager.validateDomain(domain)) { - HeartbeatReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + if (serverFilterConfigManager.validateDomain(domain)) { + HeartbeatReport report = reportManager.getHourlyReport(getStartTime(), domain, true); report.addIp(tree.getIpAddress()); List heartbeats = tree.getHeartbeats(); @@ -224,4 +220,18 @@ private void translateHeartbeat(StatusInfo info) { } } + public void setReportManager(ReportManager reportManager) { + this.reportManager = reportManager; + } + + public void setServerFilterConfigManager(ServerFilterConfigManager serverFilterConfigManager) { + this.serverFilterConfigManager = serverFilterConfigManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatDelegate.java index edcfd8982a..988d068b86 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/HeartbeatDelegate.java @@ -26,19 +26,14 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = HeartbeatAnalyzer.ID) public class HeartbeatDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_manager; @Override @@ -102,4 +97,12 @@ public HeartbeatReport parseBinary(byte[] bytes) { public HeartbeatReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager manager) { + m_manager = manager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/BaseEntity.java new file mode 100644 index 0000000000..d3a65cc7f8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.heartbeat.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.heartbeat.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/Constants.java new file mode 100644 index 0000000000..87c25420a6 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/Constants.java @@ -0,0 +1,88 @@ +package com.dianping.cat.consumer.heartbeat.model; + +public class Constants { + + public static final String ATTR_CAT_MESSAGE_OVERFLOW = "cat-message-overflow"; + + public static final String ATTR_CAT_MESSAGE_PRODUCED = "cat-message-produced"; + + public static final String ATTR_CAT_MESSAGE_SIZE = "cat-message-size"; + + public static final String ATTR_CAT_THREAD_COUNT = "cat-thread-count"; + + public static final String ATTR_CLASSPATH = "classpath"; + + public static final String ATTR_DAEMON_COUNT = "daemon-count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_FREE = "free"; + + public static final String ATTR_HEAP_USAGE = "heap-usage"; + + public static final String ATTR_HTTP_THREAD_COUNT = "http-thread-count"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_MEMORY_FREE = "memory-free"; + + public static final String ATTR_MINUTE = "minute"; + + public static final String ATTR_NEW_GC_COUNT = "new-gc-count"; + + public static final String ATTR_NONE_HEAP_USAGE = "none-heap-usage"; + + public static final String ATTR_OLD_GC_COUNT = "old-gc-count"; + + public static final String ATTR_PATH = "path"; + + public static final String ATTR_PIGEON_THREAD_COUNT = "pigeon-thread-count"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_SYSTEM_LOAD_AVERAGE = "system-load-average"; + + public static final String ATTR_THREAD_COUNT = "thread-count"; + + public static final String ATTR_TOTAL = "total"; + + public static final String ATTR_TOTAL_STARTED_COUNT = "total-started-count"; + + public static final String ATTR_USABLE = "usable"; + + public static final String ATTR_VALUE = "value"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ENTITY_DETAIL = "detail"; + + public static final String ENTITY_DETAILS = "details"; + + public static final String ENTITY_DISK = "disk"; + + public static final String ENTITY_DISKS = "disks"; + + public static final String ENTITY_EXTENSION = "extension"; + + public static final String ENTITY_EXTENSIONS = "extensions"; + + public static final String ENTITY_HEARTBEAT_REPORT = "heartbeat-report"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_PERIOD = "period"; + + public static final String ENTITY_PERIODS = "periods"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IEntity.java new file mode 100644 index 0000000000..0a8fec8c87 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.heartbeat.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IVisitor.java new file mode 100644 index 0000000000..596f857206 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/IVisitor.java @@ -0,0 +1,23 @@ +package com.dianping.cat.consumer.heartbeat.model; + +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public interface IVisitor { + + public void visitDetail(Detail detail); + + public void visitDisk(Disk disk); + + public void visitExtension(Extension extension); + + public void visitHeartbeatReport(HeartbeatReport heartbeatReport); + + public void visitMachine(Machine machine); + + public void visitPeriod(Period period); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Detail.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Detail.java new file mode 100644 index 0000000000..7cf07c0f45 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Detail.java @@ -0,0 +1,75 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DETAIL; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class Detail extends BaseEntity { + private String m_id; + + private double m_value; + + public Detail() { + } + + public Detail(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDetail(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Detail) { + Detail _o = (Detail) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public double getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Detail other) { + assertAttributeEquals(other, ENTITY_DETAIL, ATTR_ID, m_id, other.getId()); + + m_value = other.getValue(); + } + + public Detail setId(String id) { + m_id = id; + return this; + } + + public Detail setValue(double value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Disk.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Disk.java new file mode 100644 index 0000000000..750b6a7836 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Disk.java @@ -0,0 +1,101 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_PATH; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DISK; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class Disk extends BaseEntity { + private String m_path; + + private long m_total; + + private long m_free; + + private long m_usable; + + public Disk() { + } + + public Disk(String path) { + m_path = path; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDisk(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Disk) { + Disk _o = (Disk) obj; + + if (!equals(getPath(), _o.getPath())) { + return false; + } + + return true; + } + + return false; + } + + public long getFree() { + return m_free; + } + + public String getPath() { + return m_path; + } + + public long getTotal() { + return m_total; + } + + public long getUsable() { + return m_usable; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_path == null ? 0 : m_path.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Disk other) { + assertAttributeEquals(other, ENTITY_DISK, ATTR_PATH, m_path, other.getPath()); + + m_total = other.getTotal(); + + m_free = other.getFree(); + + m_usable = other.getUsable(); + } + + public Disk setFree(long free) { + m_free = free; + return this; + } + + public Disk setPath(String path) { + m_path = path; + return this; + } + + public Disk setTotal(long total) { + m_total = total; + return this; + } + + public Disk setUsable(long usable) { + m_usable = usable; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Extension.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Extension.java new file mode 100644 index 0000000000..f2510a752b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Extension.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_EXTENSION; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class Extension extends BaseEntity { + private String m_id; + + private Map m_details = new LinkedHashMap(); + + public Extension() { + } + + public Extension(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitExtension(this); + } + + public Extension addDetail(Detail detail) { + m_details.put(detail.getId(), detail); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Extension) { + Extension _o = (Extension) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Detail findDetail(String id) { + return m_details.get(id); + } + + public Detail findOrCreateDetail(String id) { + Detail detail = m_details.get(id); + + if (detail == null) { + synchronized (m_details) { + detail = m_details.get(id); + + if (detail == null) { + detail = new Detail(id); + m_details.put(id, detail); + } + } + } + + return detail; + } + + public Map getDetails() { + return m_details; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Extension other) { + assertAttributeEquals(other, ENTITY_EXTENSION, ATTR_ID, m_id, other.getId()); + + } + + public Detail removeDetail(String id) { + return m_details.remove(id); + } + + public Extension setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/HeartbeatReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/HeartbeatReport.java new file mode 100644 index 0000000000..5acf7595d2 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/HeartbeatReport.java @@ -0,0 +1,155 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_HEARTBEAT_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class HeartbeatReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_machines = new LinkedHashMap(); + + private Set m_domainNames = new LinkedHashSet(); + + private Set m_ips = new LinkedHashSet(); + + public HeartbeatReport() { + } + + public HeartbeatReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitHeartbeatReport(this); + } + + public HeartbeatReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public HeartbeatReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public HeartbeatReport addMachine(Machine machine) { + m_machines.put(machine.getIp(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HeartbeatReport) { + HeartbeatReport _o = (HeartbeatReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String ip) { + return m_machines.get(ip); + } + + public Machine findOrCreateMachine(String ip) { + Machine machine = m_machines.get(ip); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(ip); + + if (machine == null) { + machine = new Machine(ip); + m_machines.put(ip, machine); + } + } + } + + return machine; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Set getIps() { + return m_ips; + } + + public Map getMachines() { + return m_machines; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(HeartbeatReport other) { + assertAttributeEquals(other, ENTITY_HEARTBEAT_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String ip) { + return m_machines.remove(ip); + } + + public HeartbeatReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public HeartbeatReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public HeartbeatReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Machine.java new file mode 100644 index 0000000000..e9ed779e99 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Machine.java @@ -0,0 +1,119 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_MACHINE; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_ip; + + private List m_periods = new ArrayList(); + + private String m_classpath; + + public Machine() { + } + + public Machine(String ip) { + m_ip = ip; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addPeriod(Period period) { + m_periods.add(period); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getIp(), _o.getIp())) { + return false; + } + + return true; + } + + return false; + } + + public Period findPeriod(int minute) { + for (Period period : m_periods) { + if (period.getMinute() != minute) { + continue; + } + + return period; + } + + return null; + } + + public String getClasspath() { + return m_classpath; + } + + public String getIp() { + return m_ip; + } + + public List getPeriods() { + return m_periods; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_ip == null ? 0 : m_ip.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_IP, m_ip, other.getIp()); + + if (other.getClasspath() != null) { + m_classpath = other.getClasspath(); + } + } + + public Period removePeriod(int minute) { + int len = m_periods.size(); + + for (int i = 0; i < len; i++) { + Period period = m_periods.get(i); + + if (period.getMinute() != minute) { + continue; + } + + return m_periods.remove(i); + } + + return null; + } + + public Machine setClasspath(String classpath) { + m_classpath = classpath; + return this; + } + + public Machine setIp(String ip) { + m_ip = ip; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Period.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Period.java new file mode 100644 index 0000000000..54a2f8054f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/entity/Period.java @@ -0,0 +1,355 @@ +package com.dianping.cat.consumer.heartbeat.model.entity; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_MINUTE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_PERIOD; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.dianping.cat.consumer.heartbeat.model.BaseEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; + +public class Period extends BaseEntity { + private int m_minute; + + private int m_threadCount; + + private int m_daemonCount; + + private int m_totalStartedCount; + + private int m_catThreadCount; + + private int m_pigeonThreadCount; + + private int m_httpThreadCount; + + private long m_newGcCount; + + private long m_oldGcCount; + + private long m_memoryFree; + + private long m_heapUsage; + + private long m_noneHeapUsage; + + private double m_systemLoadAverage; + + private long m_catMessageProduced; + + private long m_catMessageOverflow; + + private double m_catMessageSize; + + private List m_disks = new ArrayList(); + + private Map m_extensions = new LinkedHashMap(); + + private Map m_dynamicAttributes = new LinkedHashMap(); + + public Period() { + } + + public Period(int minute) { + m_minute = minute; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitPeriod(this); + } + + public Period addDisk(Disk disk) { + m_disks.add(disk); + return this; + } + + public Period addExtension(Extension extension) { + m_extensions.put(extension.getId(), extension); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Period) { + Period _o = (Period) obj; + + if (getMinute() != _o.getMinute()) { + return false; + } + + return true; + } + + return false; + } + + public Disk findDisk(String path) { + for (Disk disk : m_disks) { + if (!equals(disk.getPath(), path)) { + continue; + } + + return disk; + } + + return null; + } + + public Extension findExtension(String id) { + return m_extensions.get(id); + } + + public Extension findOrCreateExtension(String id) { + Extension extension = m_extensions.get(id); + + if (extension == null) { + synchronized (m_extensions) { + extension = m_extensions.get(id); + + if (extension == null) { + extension = new Extension(id); + m_extensions.put(id, extension); + } + } + } + + return extension; + } + + public String getDynamicAttribute(String name) { + return m_dynamicAttributes.get(name); + } + + public Map getDynamicAttributes() { + return m_dynamicAttributes; + } + + public long getCatMessageOverflow() { + return m_catMessageOverflow; + } + + public long getCatMessageProduced() { + return m_catMessageProduced; + } + + public double getCatMessageSize() { + return m_catMessageSize; + } + + public int getCatThreadCount() { + return m_catThreadCount; + } + + public int getDaemonCount() { + return m_daemonCount; + } + + public List getDisks() { + return m_disks; + } + + public Map getExtensions() { + return m_extensions; + } + + public long getHeapUsage() { + return m_heapUsage; + } + + public int getHttpThreadCount() { + return m_httpThreadCount; + } + + public long getMemoryFree() { + return m_memoryFree; + } + + public int getMinute() { + return m_minute; + } + + public long getNewGcCount() { + return m_newGcCount; + } + + public long getNoneHeapUsage() { + return m_noneHeapUsage; + } + + public long getOldGcCount() { + return m_oldGcCount; + } + + public int getPigeonThreadCount() { + return m_pigeonThreadCount; + } + + public double getSystemLoadAverage() { + return m_systemLoadAverage; + } + + public int getThreadCount() { + return m_threadCount; + } + + public int getTotalStartedCount() { + return m_totalStartedCount; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_minute; + + return hash; + } + + @Override + public void mergeAttributes(Period other) { + assertAttributeEquals(other, ENTITY_PERIOD, ATTR_MINUTE, m_minute, other.getMinute()); + + for (Map.Entry e : other.getDynamicAttributes().entrySet()) { + m_dynamicAttributes.put(e.getKey(), e.getValue()); + } + + m_threadCount = other.getThreadCount(); + + m_daemonCount = other.getDaemonCount(); + + m_totalStartedCount = other.getTotalStartedCount(); + + m_catThreadCount = other.getCatThreadCount(); + + m_pigeonThreadCount = other.getPigeonThreadCount(); + + m_httpThreadCount = other.getHttpThreadCount(); + + m_newGcCount = other.getNewGcCount(); + + m_oldGcCount = other.getOldGcCount(); + + m_memoryFree = other.getMemoryFree(); + + m_heapUsage = other.getHeapUsage(); + + m_noneHeapUsage = other.getNoneHeapUsage(); + + m_systemLoadAverage = other.getSystemLoadAverage(); + + m_catMessageProduced = other.getCatMessageProduced(); + + m_catMessageOverflow = other.getCatMessageOverflow(); + + m_catMessageSize = other.getCatMessageSize(); + } + + public Disk removeDisk(String path) { + int len = m_disks.size(); + + for (int i = 0; i < len; i++) { + Disk disk = m_disks.get(i); + + if (!equals(disk.getPath(), path)) { + continue; + } + + return m_disks.remove(i); + } + + return null; + } + + public Extension removeExtension(String id) { + return m_extensions.remove(id); + } + + public void setDynamicAttribute(String name, String value) { + m_dynamicAttributes.put(name, value); + } + + public Period setCatMessageOverflow(long catMessageOverflow) { + m_catMessageOverflow = catMessageOverflow; + return this; + } + + public Period setCatMessageProduced(long catMessageProduced) { + m_catMessageProduced = catMessageProduced; + return this; + } + + public Period setCatMessageSize(double catMessageSize) { + m_catMessageSize = catMessageSize; + return this; + } + + public Period setCatThreadCount(int catThreadCount) { + m_catThreadCount = catThreadCount; + return this; + } + + public Period setDaemonCount(int daemonCount) { + m_daemonCount = daemonCount; + return this; + } + + public Period setHeapUsage(long heapUsage) { + m_heapUsage = heapUsage; + return this; + } + + public Period setHttpThreadCount(int httpThreadCount) { + m_httpThreadCount = httpThreadCount; + return this; + } + + public Period setMemoryFree(long memoryFree) { + m_memoryFree = memoryFree; + return this; + } + + public Period setMinute(int minute) { + m_minute = minute; + return this; + } + + public Period setNewGcCount(long newGcCount) { + m_newGcCount = newGcCount; + return this; + } + + public Period setNoneHeapUsage(long noneHeapUsage) { + m_noneHeapUsage = noneHeapUsage; + return this; + } + + public Period setOldGcCount(long oldGcCount) { + m_oldGcCount = oldGcCount; + return this; + } + + public Period setPigeonThreadCount(int pigeonThreadCount) { + m_pigeonThreadCount = pigeonThreadCount; + return this; + } + + public Period setSystemLoadAverage(double systemLoadAverage) { + m_systemLoadAverage = systemLoadAverage; + return this; + } + + public Period setThreadCount(int threadCount) { + m_threadCount = threadCount; + return this; + } + + public Period setTotalStartedCount(int totalStartedCount) { + m_totalStartedCount = totalStartedCount; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..06b3cb9eb0 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/BaseVisitor.java @@ -0,0 +1,51 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import com.dianping.cat.consumer.heartbeat.model.IVisitor; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDetail(Detail detail) { + } + + @Override + public void visitDisk(Disk disk) { + } + + @Override + public void visitExtension(Extension extension) { + for (Detail detail : extension.getDetails().values()) { + visitDetail(detail); + } + } + + @Override + public void visitHeartbeatReport(HeartbeatReport heartbeatReport) { + for (Machine machine : heartbeatReport.getMachines().values()) { + visitMachine(machine); + } + } + + @Override + public void visitMachine(Machine machine) { + for (Period period : machine.getPeriods()) { + visitPeriod(period); + } + } + + @Override + public void visitPeriod(Period period) { + for (Disk disk : period.getDisks()) { + visitDisk(disk); + } + + for (Extension extension : period.getExtensions().values()) { + visitExtension(extension); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..bd296cc3f4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultLinker.java @@ -0,0 +1,86 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDetail(final Extension parent, final Detail detail) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDetail(detail); + } + }); + } else { + parent.addDetail(detail); + } + + return true; + } + + @Override + public boolean onDisk(final Period parent, final Disk disk) { + parent.addDisk(disk); + return true; + } + + @Override + public boolean onExtension(final Period parent, final Extension extension) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addExtension(extension); + } + }); + } else { + parent.addExtension(extension); + } + + return true; + } + + @Override + public boolean onMachine(final HeartbeatReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onPeriod(final Machine parent, final Period period) { + parent.addPeriod(period); + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..4621b72f39 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultMerger.java @@ -0,0 +1,194 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.heartbeat.model.IEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private HeartbeatReport m_heartbeatReport; + + public DefaultMerger() { + } + + public DefaultMerger(HeartbeatReport heartbeatReport) { + m_heartbeatReport = heartbeatReport; + m_objs.push(heartbeatReport); + } + + public HeartbeatReport getHeartbeatReport() { + return m_heartbeatReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDetail(Detail to, Detail from) { + to.mergeAttributes(from); + } + + protected void mergeDisk(Disk to, Disk from) { + to.mergeAttributes(from); + } + + protected void mergeExtension(Extension to, Extension from) { + to.mergeAttributes(from); + } + + protected void mergeHeartbeatReport(HeartbeatReport to, HeartbeatReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + to.getIps().addAll(from.getIps()); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergePeriod(Period to, Period from) { + to.mergeAttributes(from); + } + + @Override + public void visitDetail(Detail from) { + Detail to = (Detail) m_objs.peek(); + + mergeDetail(to, from); + visitDetailChildren(to, from); + } + + protected void visitDetailChildren(Detail to, Detail from) { + } + + @Override + public void visitDisk(Disk from) { + Disk to = (Disk) m_objs.peek(); + + mergeDisk(to, from); + visitDiskChildren(to, from); + } + + protected void visitDiskChildren(Disk to, Disk from) { + } + + @Override + public void visitExtension(Extension from) { + Extension to = (Extension) m_objs.peek(); + + mergeExtension(to, from); + visitExtensionChildren(to, from); + } + + protected void visitExtensionChildren(Extension to, Extension from) { + for (Detail source : from.getDetails().values()) { + Detail target = to.findDetail(source.getId()); + + if (target == null) { + target = new Detail(source.getId()); + to.addDetail(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitHeartbeatReport(HeartbeatReport from) { + HeartbeatReport to = (HeartbeatReport) m_objs.peek(); + + mergeHeartbeatReport(to, from); + visitHeartbeatReportChildren(to, from); + } + + protected void visitHeartbeatReportChildren(HeartbeatReport to, HeartbeatReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getIp()); + + if (target == null) { + target = new Machine(source.getIp()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (Period source : from.getPeriods()) { + Period target = to.findPeriod(source.getMinute()); + + if (target == null) { + target = new Period(source.getMinute()); + to.addPeriod(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitPeriod(Period from) { + Period to = (Period) m_objs.peek(); + + mergePeriod(to, from); + visitPeriodChildren(to, from); + } + + protected void visitPeriodChildren(Period to, Period from) { + for (Disk source : from.getDisks()) { + Disk target = to.findDisk(source.getPath()); + + if (target == null) { + target = new Disk(source.getPath()); + to.addDisk(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Extension source : from.getExtensions().values()) { + Extension target = to.findExtension(source.getId()); + + if (target == null) { + target = new Extension(source.getId()); + to.addExtension(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..75bbc326da --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,308 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.util.Map; + +import com.dianping.cat.consumer.heartbeat.model.IVisitor; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(HeartbeatReport heartbeatReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(heartbeatReport, out); + return out.toByteArray(); + } + + public static void build(HeartbeatReport heartbeatReport, OutputStream out) { + heartbeatReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDetail(Detail detail) { + if (detail.getId() != null) { + writeTag(1, 1); + writeString(detail.getId()); + } + + writeTag(2, 0); + writeDouble(detail.getValue()); + + writeTag(63, 3); + } + + @Override + public void visitDisk(Disk disk) { + if (disk.getPath() != null) { + writeTag(1, 1); + writeString(disk.getPath()); + } + + writeTag(2, 0); + writeLong(disk.getTotal()); + + writeTag(3, 0); + writeLong(disk.getFree()); + + writeTag(4, 0); + writeLong(disk.getUsable()); + + writeTag(63, 3); + } + + @Override + public void visitExtension(Extension extension) { + if (extension.getId() != null) { + writeTag(1, 1); + writeString(extension.getId()); + } + + if (!extension.getDetails().isEmpty()) { + writeTag(33, 2); + writeInt(extension.getDetails().size()); + + for (Detail detail : extension.getDetails().values()) { + detail.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitHeartbeatReport(HeartbeatReport heartbeatReport) { + writeTag(63, 0); + + if (heartbeatReport.getDomain() != null) { + writeTag(1, 1); + writeString(heartbeatReport.getDomain()); + } + + if (heartbeatReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(heartbeatReport.getStartTime()); + } + + if (heartbeatReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(heartbeatReport.getEndTime()); + } + + if (heartbeatReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(heartbeatReport.getDomainNames().size()); + + for (String domain : heartbeatReport.getDomainNames()) { + writeString(domain); + } + } + + if (heartbeatReport.getIps() != null) { + writeTag(5, 2); + writeInt(heartbeatReport.getIps().size()); + + for (String ip : heartbeatReport.getIps()) { + writeString(ip); + } + } + + if (!heartbeatReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(heartbeatReport.getMachines().size()); + + for (Machine machine : heartbeatReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getIp() != null) { + writeTag(1, 1); + writeString(machine.getIp()); + } + + if (machine.getClasspath() != null) { + writeTag(2, 1); + writeString(machine.getClasspath()); + } + + if (!machine.getPeriods().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getPeriods().size()); + + for (Period period : machine.getPeriods()) { + period.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitPeriod(Period period) { + writeTag(1, 0); + writeInt(period.getMinute()); + + writeTag(2, 0); + writeInt(period.getThreadCount()); + + writeTag(3, 0); + writeInt(period.getDaemonCount()); + + writeTag(4, 0); + writeInt(period.getTotalStartedCount()); + + writeTag(5, 0); + writeInt(period.getCatThreadCount()); + + writeTag(6, 0); + writeInt(period.getPigeonThreadCount()); + + writeTag(7, 0); + writeInt(period.getHttpThreadCount()); + + writeTag(8, 0); + writeLong(period.getNewGcCount()); + + writeTag(9, 0); + writeLong(period.getOldGcCount()); + + writeTag(10, 0); + writeLong(period.getMemoryFree()); + + writeTag(11, 0); + writeLong(period.getHeapUsage()); + + writeTag(12, 0); + writeLong(period.getNoneHeapUsage()); + + writeTag(13, 0); + writeDouble(period.getSystemLoadAverage()); + + writeTag(14, 0); + writeLong(period.getCatMessageProduced()); + + writeTag(15, 0); + writeLong(period.getCatMessageOverflow()); + + writeTag(16, 0); + writeDouble(period.getCatMessageSize()); + + if (!period.getDisks().isEmpty()) { + writeTag(33, 2); + writeInt(period.getDisks().size()); + + for (Disk disk : period.getDisks()) { + disk.accept(m_visitor); + } + } + + if (!period.getExtensions().isEmpty()) { + writeTag(34, 2); + writeInt(period.getExtensions().size()); + + for (Extension extension : period.getExtensions().values()) { + extension.accept(m_visitor); + } + } + + if (!period.getDynamicAttributes().isEmpty()) { + writeTag(63, 2); + writeInt(period.getDynamicAttributes().size()); + + for (Map.Entry dynamicAttribute : period.getDynamicAttributes().entrySet()) { + writeString(dynamicAttribute.getKey()); + writeString(dynamicAttribute.getValue()); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..8d37a46752 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultNativeParser.java @@ -0,0 +1,388 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.util.Map; + +import com.dianping.cat.consumer.heartbeat.model.IVisitor; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static HeartbeatReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static HeartbeatReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + HeartbeatReport heartbeatReport = new HeartbeatReport(); + + try { + heartbeatReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return heartbeatReport; + } + + @Override + public void visitDetail(Detail detail) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDetailChildren(detail, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDetailChildren(Detail detail, int _field, int _type) { + switch (_field) { + case 1: + detail.setId(readString()); + break; + case 2: + detail.setValue(readDouble()); + break; + } + } + + @Override + public void visitDisk(Disk disk) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDiskChildren(disk, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDiskChildren(Disk disk, int _field, int _type) { + switch (_field) { + case 1: + disk.setPath(readString()); + break; + case 2: + disk.setTotal(readLong()); + break; + case 3: + disk.setFree(readLong()); + break; + case 4: + disk.setUsable(readLong()); + break; + } + } + + @Override + public void visitExtension(Extension extension) { + byte tag; + + while ((tag = readTag()) != -1) { + visitExtensionChildren(extension, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitExtensionChildren(Extension extension, int _field, int _type) { + switch (_field) { + case 1: + extension.setId(readString()); + break; + case 33: + if (_type == 1) { + Detail detail = new Detail(); + + visitDetail(detail); + m_linker.onDetail(extension, detail); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Detail detail = new Detail(); + + visitDetail(detail); + m_linker.onDetail(extension, detail); + } + } + break; + } + } + + @Override + public void visitHeartbeatReport(HeartbeatReport heartbeatReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitHeartbeatReportChildren(heartbeatReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitHeartbeatReportChildren(HeartbeatReport heartbeatReport, int _field, int _type) { + switch (_field) { + case 1: + heartbeatReport.setDomain(readString()); + break; + case 2: + heartbeatReport.setStartTime(readDate()); + break; + case 3: + heartbeatReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + heartbeatReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + heartbeatReport.addDomain(readString()); + } + } + break; + case 5: + if (_type == 1) { + heartbeatReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + heartbeatReport.addIp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(heartbeatReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(heartbeatReport, machine); + } + } + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setIp(readString()); + break; + case 2: + machine.setClasspath(readString()); + break; + case 33: + if (_type == 1) { + Period period = new Period(); + + visitPeriod(period); + m_linker.onPeriod(machine, period); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Period period = new Period(); + + visitPeriod(period); + m_linker.onPeriod(machine, period); + } + } + break; + } + } + + @Override + public void visitPeriod(Period period) { + byte tag; + + while ((tag = readTag()) != -1) { + visitPeriodChildren(period, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitPeriodChildren(Period period, int _field, int _type) { + switch (_field) { + case 1: + period.setMinute(readInt()); + break; + case 2: + period.setThreadCount(readInt()); + break; + case 3: + period.setDaemonCount(readInt()); + break; + case 4: + period.setTotalStartedCount(readInt()); + break; + case 5: + period.setCatThreadCount(readInt()); + break; + case 6: + period.setPigeonThreadCount(readInt()); + break; + case 7: + period.setHttpThreadCount(readInt()); + break; + case 8: + period.setNewGcCount(readLong()); + break; + case 9: + period.setOldGcCount(readLong()); + break; + case 10: + period.setMemoryFree(readLong()); + break; + case 11: + period.setHeapUsage(readLong()); + break; + case 12: + period.setNoneHeapUsage(readLong()); + break; + case 13: + period.setSystemLoadAverage(readDouble()); + break; + case 14: + period.setCatMessageProduced(readLong()); + break; + case 15: + period.setCatMessageOverflow(readLong()); + break; + case 16: + period.setCatMessageSize(readDouble()); + break; + case 33: + if (_type == 1) { + Disk disk = new Disk(); + + visitDisk(disk); + m_linker.onDisk(period, disk); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Disk disk = new Disk(); + + visitDisk(disk); + m_linker.onDisk(period, disk); + } + } + break; + case 34: + if (_type == 1) { + Extension extension = new Extension(); + + visitExtension(extension); + m_linker.onExtension(period, extension); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Extension extension = new Extension(); + + visitExtension(extension); + m_linker.onExtension(period, extension); + } + } + break; + case 63: + Map dynamicAttribute = period.getDynamicAttributes(); + + for (int i = readInt(); i > 0; i--) { + String key = readString(); + String value = readString(); + + dynamicAttribute.put(key, value); + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..38ac5bba9b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxMaker.java @@ -0,0 +1,288 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_OVERFLOW; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_PRODUCED; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_SIZE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CLASSPATH; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_DAEMON_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_FREE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_HEAP_USAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_HTTP_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_MEMORY_FREE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_MINUTE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_NEW_GC_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_NONE_HEAP_USAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_OLD_GC_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_PATH; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_PIGEON_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_SYSTEM_LOAD_AVERAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_TOTAL; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_TOTAL_STARTED_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_USABLE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_VALUE; + +import java.util.Map; +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Detail buildDetail(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String value = attributes.getValue(ATTR_VALUE); + Detail detail = new Detail(id); + + if (value != null) { + detail.setValue(convert(Double.class, value, 0.0)); + } + + return detail; + } + + @Override + public Disk buildDisk(Attributes attributes) { + String path = attributes.getValue(ATTR_PATH); + String total = attributes.getValue(ATTR_TOTAL); + String free = attributes.getValue(ATTR_FREE); + String usable = attributes.getValue(ATTR_USABLE); + Disk disk = new Disk(path); + + if (total != null) { + disk.setTotal(convert(Long.class, total, 0L)); + } + + if (free != null) { + disk.setFree(convert(Long.class, free, 0L)); + } + + if (usable != null) { + disk.setUsable(convert(Long.class, usable, 0L)); + } + + return disk; + } + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Extension buildExtension(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Extension extension = new Extension(id); + + return extension; + } + + @Override + public HeartbeatReport buildHeartbeatReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + HeartbeatReport heartbeatReport = new HeartbeatReport(domain); + + if (startTime != null) { + heartbeatReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + heartbeatReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return heartbeatReport; + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String ip = attributes.getValue(ATTR_IP); + String classpath = attributes.getValue(ATTR_CLASSPATH); + Machine machine = new Machine(ip); + + if (classpath != null) { + machine.setClasspath(classpath); + } + + return machine; + } + + @Override + public Period buildPeriod(Attributes attributes) { + String minute = attributes.getValue(ATTR_MINUTE); + String threadCount = attributes.getValue(ATTR_THREAD_COUNT); + String daemonCount = attributes.getValue(ATTR_DAEMON_COUNT); + String totalStartedCount = attributes.getValue(ATTR_TOTAL_STARTED_COUNT); + String catThreadCount = attributes.getValue(ATTR_CAT_THREAD_COUNT); + String pigeonThreadCount = attributes.getValue(ATTR_PIGEON_THREAD_COUNT); + String httpThreadCount = attributes.getValue(ATTR_HTTP_THREAD_COUNT); + String newGcCount = attributes.getValue(ATTR_NEW_GC_COUNT); + String oldGcCount = attributes.getValue(ATTR_OLD_GC_COUNT); + String memoryFree = attributes.getValue(ATTR_MEMORY_FREE); + String heapUsage = attributes.getValue(ATTR_HEAP_USAGE); + String noneHeapUsage = attributes.getValue(ATTR_NONE_HEAP_USAGE); + String systemLoadAverage = attributes.getValue(ATTR_SYSTEM_LOAD_AVERAGE); + String catMessageProduced = attributes.getValue(ATTR_CAT_MESSAGE_PRODUCED); + String catMessageOverflow = attributes.getValue(ATTR_CAT_MESSAGE_OVERFLOW); + String catMessageSize = attributes.getValue(ATTR_CAT_MESSAGE_SIZE); + Period period = new Period(minute == null ? 0 : convert(Integer.class, minute, 0)); + + if (threadCount != null) { + period.setThreadCount(convert(Integer.class, threadCount, 0)); + } + + if (daemonCount != null) { + period.setDaemonCount(convert(Integer.class, daemonCount, 0)); + } + + if (totalStartedCount != null) { + period.setTotalStartedCount(convert(Integer.class, totalStartedCount, 0)); + } + + if (catThreadCount != null) { + period.setCatThreadCount(convert(Integer.class, catThreadCount, 0)); + } + + if (pigeonThreadCount != null) { + period.setPigeonThreadCount(convert(Integer.class, pigeonThreadCount, 0)); + } + + if (httpThreadCount != null) { + period.setHttpThreadCount(convert(Integer.class, httpThreadCount, 0)); + } + + if (newGcCount != null) { + period.setNewGcCount(convert(Long.class, newGcCount, 0L)); + } + + if (oldGcCount != null) { + period.setOldGcCount(convert(Long.class, oldGcCount, 0L)); + } + + if (memoryFree != null) { + period.setMemoryFree(convert(Long.class, memoryFree, 0L)); + } + + if (heapUsage != null) { + period.setHeapUsage(convert(Long.class, heapUsage, 0L)); + } + + if (noneHeapUsage != null) { + period.setNoneHeapUsage(convert(Long.class, noneHeapUsage, 0L)); + } + + if (systemLoadAverage != null) { + period.setSystemLoadAverage(toNumber(systemLoadAverage, "0.00", 0).doubleValue()); + } + + if (catMessageProduced != null) { + period.setCatMessageProduced(convert(Long.class, catMessageProduced, 0L)); + } + + if (catMessageOverflow != null) { + period.setCatMessageOverflow(convert(Long.class, catMessageOverflow, 0L)); + } + + if (catMessageSize != null) { + period.setCatMessageSize(toNumber(catMessageSize, "0.00", 0).doubleValue()); + } + + Map dynamicAttributes = period.getDynamicAttributes(); + int _length = attributes == null ? 0 : attributes.getLength(); + + for (int i = 0; i < _length; i++) { + String _name = attributes.getQName(i); + String _value = attributes.getValue(i); + + dynamicAttributes.put(_name, _value); + } + + dynamicAttributes.remove(ATTR_MINUTE); + dynamicAttributes.remove(ATTR_THREAD_COUNT); + dynamicAttributes.remove(ATTR_DAEMON_COUNT); + dynamicAttributes.remove(ATTR_TOTAL_STARTED_COUNT); + dynamicAttributes.remove(ATTR_CAT_THREAD_COUNT); + dynamicAttributes.remove(ATTR_PIGEON_THREAD_COUNT); + dynamicAttributes.remove(ATTR_HTTP_THREAD_COUNT); + dynamicAttributes.remove(ATTR_NEW_GC_COUNT); + dynamicAttributes.remove(ATTR_OLD_GC_COUNT); + dynamicAttributes.remove(ATTR_MEMORY_FREE); + dynamicAttributes.remove(ATTR_HEAP_USAGE); + dynamicAttributes.remove(ATTR_NONE_HEAP_USAGE); + dynamicAttributes.remove(ATTR_SYSTEM_LOAD_AVERAGE); + dynamicAttributes.remove(ATTR_CAT_MESSAGE_PRODUCED); + dynamicAttributes.remove(ATTR_CAT_MESSAGE_OVERFLOW); + dynamicAttributes.remove(ATTR_CAT_MESSAGE_SIZE); + + return period; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..5d5e4fb0f4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultSaxParser.java @@ -0,0 +1,348 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_DOMAIN_NAMES; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_IPS; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DETAIL; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DISK; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_EXTENSION; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_HEARTBEAT_REPORT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_PERIOD; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.heartbeat.model.IEntity; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static HeartbeatReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(HeartbeatReport.class, new InputSource(removeBOM(in))); + } + + public static HeartbeatReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(HeartbeatReport.class, new InputSource(removeBOM(reader))); + } + + public static HeartbeatReport parse(String xml) throws SAXException, IOException { + return parseEntity(HeartbeatReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof HeartbeatReport) { + HeartbeatReport heartbeatReport = (HeartbeatReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + heartbeatReport.addDomain(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + heartbeatReport.addIp(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDetail(Detail parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForDisk(Disk parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForExtension(Extension parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DETAIL.equals(qName)) { + Detail detail = m_maker.buildDetail(attributes); + + m_linker.onDetail(parentObj, detail); + m_objs.push(detail); + } else { + throw new SAXException(String.format("Element(%s) is not expected under extension!", qName)); + } + + m_tags.push(qName); + } + + private void parseForHeartbeatReport(HeartbeatReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under heartbeat-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PERIOD.equals(qName)) { + Period period = m_maker.buildPeriod(attributes); + + m_linker.onPeriod(parentObj, period); + m_objs.push(period); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForPeriod(Period parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DISK.equals(qName)) { + Disk disk = m_maker.buildDisk(attributes); + + m_linker.onDisk(parentObj, disk); + m_objs.push(disk); + } else if (ENTITY_EXTENSION.equals(qName)) { + Extension extension = m_maker.buildExtension(attributes); + + m_linker.onExtension(parentObj, extension); + m_objs.push(extension); + } else { + throw new SAXException(String.format("Element(%s) is not expected under period!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_HEARTBEAT_REPORT.equals(qName)) { + HeartbeatReport heartbeatReport = m_maker.buildHeartbeatReport(attributes); + + m_entity = heartbeatReport; + m_objs.push(heartbeatReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_PERIOD.equals(qName)) { + Period period = m_maker.buildPeriod(attributes); + + m_entity = period; + m_objs.push(period); + m_tags.push(qName); + } else if (ENTITY_DISK.equals(qName)) { + Disk disk = m_maker.buildDisk(attributes); + + m_entity = disk; + m_objs.push(disk); + m_tags.push(qName); + } else if (ENTITY_EXTENSION.equals(qName)) { + Extension extension = m_maker.buildExtension(attributes); + + m_entity = extension; + m_objs.push(extension); + m_tags.push(qName); + } else if (ENTITY_DETAIL.equals(qName)) { + Detail detail = m_maker.buildDetail(attributes); + + m_entity = detail; + m_objs.push(detail); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof HeartbeatReport) { + parseForHeartbeatReport((HeartbeatReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof Period) { + parseForPeriod((Period) parent, tag, qName, attributes); + } else if (parent instanceof Disk) { + parseForDisk((Disk) parent, tag, qName, attributes); + } else if (parent instanceof Extension) { + parseForExtension((Extension) parent, tag, qName, attributes); + } else if (parent instanceof Detail) { + parseForDetail((Detail) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..4528628988 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,369 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_OVERFLOW; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_PRODUCED; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_MESSAGE_SIZE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CAT_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_CLASSPATH; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_DAEMON_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_FREE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_HEAP_USAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_HTTP_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_MEMORY_FREE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_MINUTE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_NEW_GC_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_NONE_HEAP_USAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_OLD_GC_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_PATH; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_PIGEON_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_SYSTEM_LOAD_AVERAGE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_THREAD_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_TOTAL; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_TOTAL_STARTED_COUNT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_USABLE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DETAIL; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_DISK; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_EXTENSION; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_HEARTBEAT_REPORT; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.heartbeat.model.Constants.ENTITY_PERIOD; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.heartbeat.model.IEntity; +import com.dianping.cat.consumer.heartbeat.model.IVisitor; +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitDetail(Detail detail) { + startTag(ENTITY_DETAIL, true, null, ATTR_ID, detail.getId(), ATTR_VALUE, detail.getValue()); + } + + @Override + public void visitDisk(Disk disk) { + startTag(ENTITY_DISK, true, null, ATTR_PATH, disk.getPath(), ATTR_TOTAL, disk.getTotal(), ATTR_FREE, disk.getFree(), ATTR_USABLE, disk.getUsable()); + } + + @Override + public void visitExtension(Extension extension) { + startTag(ENTITY_EXTENSION, null, ATTR_ID, extension.getId()); + + if (!extension.getDetails().isEmpty()) { + for (Detail detail : extension.getDetails().values()) { + detail.accept(m_visitor); + } + } + + endTag(ENTITY_EXTENSION); + } + + @Override + public void visitHeartbeatReport(HeartbeatReport heartbeatReport) { + startTag(ENTITY_HEARTBEAT_REPORT, null, ATTR_DOMAIN, heartbeatReport.getDomain(), ATTR_STARTTIME, toString(heartbeatReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(heartbeatReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!heartbeatReport.getDomainNames().isEmpty()) { + for (String domain : heartbeatReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!heartbeatReport.getIps().isEmpty()) { + for (String ip : heartbeatReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!heartbeatReport.getMachines().isEmpty()) { + for (Machine machine : heartbeatReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_HEARTBEAT_REPORT); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_IP, machine.getIp(), ATTR_CLASSPATH, machine.getClasspath()); + + if (!machine.getPeriods().isEmpty()) { + for (Period period : machine.getPeriods()) { + period.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitPeriod(Period period) { + startTag(ENTITY_PERIOD, period.getDynamicAttributes(), ATTR_MINUTE, period.getMinute(), ATTR_THREAD_COUNT, period.getThreadCount(), ATTR_DAEMON_COUNT, period.getDaemonCount(), ATTR_TOTAL_STARTED_COUNT, period.getTotalStartedCount(), ATTR_CAT_THREAD_COUNT, period.getCatThreadCount(), ATTR_PIGEON_THREAD_COUNT, period.getPigeonThreadCount(), ATTR_HTTP_THREAD_COUNT, period.getHttpThreadCount(), ATTR_NEW_GC_COUNT, period.getNewGcCount(), ATTR_OLD_GC_COUNT, period.getOldGcCount(), ATTR_MEMORY_FREE, period.getMemoryFree(), ATTR_HEAP_USAGE, period.getHeapUsage(), ATTR_NONE_HEAP_USAGE, period.getNoneHeapUsage(), ATTR_SYSTEM_LOAD_AVERAGE, toString(period.getSystemLoadAverage(), "0.00"), ATTR_CAT_MESSAGE_PRODUCED, period.getCatMessageProduced(), ATTR_CAT_MESSAGE_OVERFLOW, period.getCatMessageOverflow(), ATTR_CAT_MESSAGE_SIZE, toString(period.getCatMessageSize(), "0.00")); + + if (!period.getDisks().isEmpty()) { + for (Disk disk : period.getDisks()) { + disk.accept(m_visitor); + } + } + + if (!period.getExtensions().isEmpty()) { + for (Extension extension : period.getExtensions().values()) { + extension.accept(m_visitor); + } + } + + endTag(ENTITY_PERIOD); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/ILinker.java new file mode 100644 index 0000000000..a12bc72130 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/ILinker.java @@ -0,0 +1,21 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public interface ILinker { + + public boolean onDetail(Extension parent, Detail detail); + + public boolean onDisk(Period parent, Disk disk); + + public boolean onExtension(Period parent, Extension extension); + + public boolean onMachine(HeartbeatReport parent, Machine machine); + + public boolean onPeriod(Machine parent, Period period); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IMaker.java new file mode 100644 index 0000000000..c5a56fabc3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IMaker.java @@ -0,0 +1,27 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public interface IMaker { + + public Detail buildDetail(T node); + + public Disk buildDisk(T node); + + public String buildDomain(T node); + + public Extension buildExtension(T node); + + public HeartbeatReport buildHeartbeatReport(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public Period buildPeriod(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IParser.java new file mode 100644 index 0000000000..54bd0789f8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/heartbeat/model/transform/IParser.java @@ -0,0 +1,22 @@ +package com.dianping.cat.consumer.heartbeat.model.transform; + +import com.dianping.cat.consumer.heartbeat.model.entity.Detail; +import com.dianping.cat.consumer.heartbeat.model.entity.Disk; +import com.dianping.cat.consumer.heartbeat.model.entity.Extension; +import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; +import com.dianping.cat.consumer.heartbeat.model.entity.Machine; +import com.dianping.cat.consumer.heartbeat.model.entity.Period; + +public interface IParser { + public HeartbeatReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDetail(IMaker maker, ILinker linker, Detail parent, T node); + + public void parseForDisk(IMaker maker, ILinker linker, Disk parent, T node); + + public void parseForExtension(IMaker maker, ILinker linker, Extension parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForPeriod(IMaker maker, ILinker linker, Period parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixAnalyzer.java index 3fe35ae5b3..0090a5ace2 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixAnalyzer.java @@ -19,7 +19,9 @@ package com.dianping.cat.consumer.matrix; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.matrix.model.entity.Matrix; import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.consumer.matrix.model.entity.Ratio; @@ -28,50 +30,45 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = MatrixAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class MatrixAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + MatrixAnalyzer.ID) +@Scope("prototype") +public class MatrixAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "matrix"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = MatrixAnalyzer.ID + "ReportManager") + private ReportManager matrixReportManager; @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + matrixReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + matrixReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public MatrixReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, false); + return matrixReportManager.getHourlyReport(getStartTime(), domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return matrixReportManager; } @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + matrixReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override @@ -86,7 +83,7 @@ public boolean isEligable(MessageTree tree) { @Override public void process(MessageTree tree) { String domain = tree.getDomain(); - MatrixReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + MatrixReport report = matrixReportManager.getHourlyReport(getStartTime(), domain, true); Message message = tree.getMessage(); if (message instanceof Transaction) { @@ -155,4 +152,14 @@ private void processTransaction(MessageTree tree, Transaction t, Map reportManager) { + matrixReportManager = reportManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixDelegate.java index 2373382f49..f42db1be19 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/MatrixDelegate.java @@ -21,9 +21,6 @@ import java.util.Date; import java.util.Map; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.consumer.matrix.model.transform.DefaultNativeBuilder; @@ -33,13 +30,10 @@ import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -@Named(type = ReportDelegate.class, value = MatrixAnalyzer.ID) public class MatrixDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_configManager; @Override @@ -105,4 +99,12 @@ public MatrixReport parseXml(String xml) throws Exception { return report; } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager configManager) { + m_configManager = configManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/BaseEntity.java new file mode 100644 index 0000000000..65dd7ba822 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.matrix.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.matrix.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/Constants.java new file mode 100644 index 0000000000..5814256dd1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/Constants.java @@ -0,0 +1,40 @@ +package com.dianping.cat.consumer.matrix.model; + +public class Constants { + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_MAX = "max"; + + public static final String ATTR_MIN = "min"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_TOTALCOUNT = "totalCount"; + + public static final String ATTR_TOTALTIME = "totalTime"; + + public static final String ATTR_TYPE = "type"; + + public static final String ATTR_URL = "url"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ENTITY_MATRIX = "matrix"; + + public static final String ENTITY_MATRIXS = "matrixs"; + + public static final String ENTITY_MATRIX_REPORT = "matrix-report"; + + public static final String ENTITY_RATIO = "ratio"; + + public static final String ENTITY_RATIOS = "ratios"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IEntity.java new file mode 100644 index 0000000000..79096cf41b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.matrix.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IVisitor.java new file mode 100644 index 0000000000..3116c7bcc8 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.consumer.matrix.model; + +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public interface IVisitor { + + public void visitMatrix(Matrix matrix); + + public void visitMatrixReport(MatrixReport matrixReport); + + public void visitRatio(Ratio ratio); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Matrix.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Matrix.java new file mode 100644 index 0000000000..651c4cd35f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Matrix.java @@ -0,0 +1,167 @@ +package com.dianping.cat.consumer.matrix.model.entity; + +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.matrix.model.BaseEntity; +import com.dianping.cat.consumer.matrix.model.IVisitor; + +public class Matrix extends BaseEntity { + private String m_type; + + private String m_name; + + private int m_count; + + private long m_totalTime; + + private String m_url; + + private Map m_ratios = new LinkedHashMap(); + + public Matrix() { + } + + public Matrix(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMatrix(this); + } + + public Matrix addRatio(Ratio ratio) { + m_ratios.put(ratio.getType(), ratio); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Matrix) { + Matrix _o = (Matrix) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public Ratio findRatio(String type) { + return m_ratios.get(type); + } + + public Ratio findOrCreateRatio(String type) { + Ratio ratio = m_ratios.get(type); + + if (ratio == null) { + synchronized (m_ratios) { + ratio = m_ratios.get(type); + + if (ratio == null) { + ratio = new Ratio(type); + m_ratios.put(type, ratio); + } + } + } + + return ratio; + } + + public int getCount() { + return m_count; + } + + public String getName() { + return m_name; + } + + public Map getRatios() { + return m_ratios; + } + + public long getTotalTime() { + return m_totalTime; + } + + public String getType() { + return m_type; + } + + public String getUrl() { + return m_url; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + public Matrix incCount() { + m_count++; + return this; + } + + public Matrix incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Matrix other) { + assertAttributeEquals(other, ENTITY_MATRIX, ATTR_NAME, m_name, other.getName()); + + if (other.getType() != null) { + m_type = other.getType(); + } + + m_count = other.getCount(); + + m_totalTime = other.getTotalTime(); + + if (other.getUrl() != null) { + m_url = other.getUrl(); + } + } + + public Ratio removeRatio(String type) { + return m_ratios.remove(type); + } + + public Matrix setCount(int count) { + m_count = count; + return this; + } + + public Matrix setName(String name) { + m_name = name; + return this; + } + + public Matrix setTotalTime(long totalTime) { + m_totalTime = totalTime; + return this; + } + + public Matrix setType(String type) { + m_type = type; + return this; + } + + public Matrix setUrl(String url) { + m_url = url; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/MatrixReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/MatrixReport.java new file mode 100644 index 0000000000..28d31d8ca2 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/MatrixReport.java @@ -0,0 +1,144 @@ +package com.dianping.cat.consumer.matrix.model.entity; + +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.matrix.model.BaseEntity; +import com.dianping.cat.consumer.matrix.model.IVisitor; + +public class MatrixReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Set m_domainNames = new LinkedHashSet(); + + private Map m_matrixs = new LinkedHashMap(); + + public MatrixReport() { + } + + public MatrixReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMatrixReport(this); + } + + public MatrixReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public MatrixReport addMatrix(Matrix matrix) { + m_matrixs.put(matrix.getName(), matrix); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MatrixReport) { + MatrixReport _o = (MatrixReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Matrix findMatrix(String name) { + return m_matrixs.get(name); + } + + public Matrix findOrCreateMatrix(String name) { + Matrix matrix = m_matrixs.get(name); + + if (matrix == null) { + synchronized (m_matrixs) { + matrix = m_matrixs.get(name); + + if (matrix == null) { + matrix = new Matrix(name); + m_matrixs.put(name, matrix); + } + } + } + + return matrix; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Map getMatrixs() { + return m_matrixs; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(MatrixReport other) { + assertAttributeEquals(other, ENTITY_MATRIX_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Matrix removeMatrix(String name) { + return m_matrixs.remove(name); + } + + public MatrixReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public MatrixReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public MatrixReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Ratio.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Ratio.java new file mode 100644 index 0000000000..737fd0f15a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/entity/Ratio.java @@ -0,0 +1,139 @@ +package com.dianping.cat.consumer.matrix.model.entity; + +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_RATIO; + +import com.dianping.cat.consumer.matrix.model.BaseEntity; +import com.dianping.cat.consumer.matrix.model.IVisitor; + +public class Ratio extends BaseEntity { + private String m_type; + + private int m_min; + + private int m_max; + + private int m_totalCount; + + private long m_totalTime; + + private String m_url; + + public Ratio() { + } + + public Ratio(String type) { + m_type = type; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRatio(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Ratio) { + Ratio _o = (Ratio) obj; + + if (!equals(getType(), _o.getType())) { + return false; + } + + return true; + } + + return false; + } + + public int getMax() { + return m_max; + } + + public int getMin() { + return m_min; + } + + public int getTotalCount() { + return m_totalCount; + } + + public long getTotalTime() { + return m_totalTime; + } + + public String getType() { + return m_type; + } + + public String getUrl() { + return m_url; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_type == null ? 0 : m_type.hashCode()); + + return hash; + } + + public Ratio incTotalCount() { + m_totalCount++; + return this; + } + + public Ratio incTotalCount(int totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(Ratio other) { + assertAttributeEquals(other, ENTITY_RATIO, ATTR_TYPE, m_type, other.getType()); + + m_min = other.getMin(); + + m_max = other.getMax(); + + m_totalCount = other.getTotalCount(); + + m_totalTime = other.getTotalTime(); + + if (other.getUrl() != null) { + m_url = other.getUrl(); + } + } + + public Ratio setMax(int max) { + m_max = max; + return this; + } + + public Ratio setMin(int min) { + m_min = min; + return this; + } + + public Ratio setTotalCount(int totalCount) { + m_totalCount = totalCount; + return this; + } + + public Ratio setTotalTime(long totalTime) { + m_totalTime = totalTime; + return this; + } + + public Ratio setType(String type) { + m_type = type; + return this; + } + + public Ratio setUrl(String url) { + m_url = url; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..389663182f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/BaseVisitor.java @@ -0,0 +1,26 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import com.dianping.cat.consumer.matrix.model.IVisitor; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitMatrix(Matrix matrix) { + for (Ratio ratio : matrix.getRatios().values()) { + visitRatio(ratio); + } + } + + @Override + public void visitMatrixReport(MatrixReport matrixReport) { + for (Matrix matrix : matrixReport.getMatrixs().values()) { + visitMatrix(matrix); + } + } + + @Override + public void visitRatio(Ratio ratio) { + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..334fb44d89 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultLinker.java @@ -0,0 +1,55 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onMatrix(final MatrixReport parent, final Matrix matrix) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMatrix(matrix); + } + }); + } else { + parent.addMatrix(matrix); + } + + return true; + } + + @Override + public boolean onRatio(final Matrix parent, final Ratio ratio) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRatio(ratio); + } + }); + } else { + parent.addRatio(ratio); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..12303798cf --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultMerger.java @@ -0,0 +1,108 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.matrix.model.IEntity; +import com.dianping.cat.consumer.matrix.model.IVisitor; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private MatrixReport m_matrixReport; + + public DefaultMerger() { + } + + public DefaultMerger(MatrixReport matrixReport) { + m_matrixReport = matrixReport; + m_objs.push(matrixReport); + } + + public MatrixReport getMatrixReport() { + return m_matrixReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeMatrix(Matrix to, Matrix from) { + to.mergeAttributes(from); + } + + protected void mergeMatrixReport(MatrixReport to, MatrixReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + } + + protected void mergeRatio(Ratio to, Ratio from) { + to.mergeAttributes(from); + } + + @Override + public void visitMatrix(Matrix from) { + Matrix to = (Matrix) m_objs.peek(); + + mergeMatrix(to, from); + visitMatrixChildren(to, from); + } + + protected void visitMatrixChildren(Matrix to, Matrix from) { + for (Ratio source : from.getRatios().values()) { + Ratio target = to.findRatio(source.getType()); + + if (target == null) { + target = new Ratio(source.getType()); + to.addRatio(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitMatrixReport(MatrixReport from) { + MatrixReport to = (MatrixReport) m_objs.peek(); + + mergeMatrixReport(to, from); + visitMatrixReportChildren(to, from); + } + + protected void visitMatrixReportChildren(MatrixReport to, MatrixReport from) { + for (Matrix source : from.getMatrixs().values()) { + Matrix target = to.findMatrix(source.getName()); + + if (target == null) { + target = new Matrix(source.getName()); + to.addMatrix(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitRatio(Ratio from) { + Ratio to = (Ratio) m_objs.peek(); + + mergeRatio(to, from); + visitRatioChildren(to, from); + } + + protected void visitRatioChildren(Ratio to, Ratio from) { + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..27d82b949f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,192 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.matrix.model.IVisitor; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(MatrixReport matrixReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(matrixReport, out); + return out.toByteArray(); + } + + public static void build(MatrixReport matrixReport, OutputStream out) { + matrixReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitMatrix(Matrix matrix) { + if (matrix.getType() != null) { + writeTag(1, 1); + writeString(matrix.getType()); + } + + if (matrix.getName() != null) { + writeTag(2, 1); + writeString(matrix.getName()); + } + + writeTag(3, 0); + writeInt(matrix.getCount()); + + writeTag(4, 0); + writeLong(matrix.getTotalTime()); + + if (matrix.getUrl() != null) { + writeTag(5, 1); + writeString(matrix.getUrl()); + } + + if (!matrix.getRatios().isEmpty()) { + writeTag(33, 2); + writeInt(matrix.getRatios().size()); + + for (Ratio ratio : matrix.getRatios().values()) { + ratio.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitMatrixReport(MatrixReport matrixReport) { + writeTag(63, 0); + + if (matrixReport.getDomain() != null) { + writeTag(1, 1); + writeString(matrixReport.getDomain()); + } + + if (matrixReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(matrixReport.getStartTime()); + } + + if (matrixReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(matrixReport.getEndTime()); + } + + if (matrixReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(matrixReport.getDomainNames().size()); + + for (String domain : matrixReport.getDomainNames()) { + writeString(domain); + } + } + + if (!matrixReport.getMatrixs().isEmpty()) { + writeTag(33, 2); + writeInt(matrixReport.getMatrixs().size()); + + for (Matrix matrix : matrixReport.getMatrixs().values()) { + matrix.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitRatio(Ratio ratio) { + if (ratio.getType() != null) { + writeTag(1, 1); + writeString(ratio.getType()); + } + + writeTag(2, 0); + writeInt(ratio.getMin()); + + writeTag(3, 0); + writeInt(ratio.getMax()); + + writeTag(4, 0); + writeInt(ratio.getTotalCount()); + + writeTag(5, 0); + writeLong(ratio.getTotalTime()); + + if (ratio.getUrl() != null) { + writeTag(6, 1); + writeString(ratio.getUrl()); + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..00ceab1763 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultNativeParser.java @@ -0,0 +1,227 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.matrix.model.IVisitor; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static MatrixReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static MatrixReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + MatrixReport matrixReport = new MatrixReport(); + + try { + matrixReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return matrixReport; + } + + @Override + public void visitMatrix(Matrix matrix) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMatrixChildren(matrix, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMatrixChildren(Matrix matrix, int _field, int _type) { + switch (_field) { + case 1: + matrix.setType(readString()); + break; + case 2: + matrix.setName(readString()); + break; + case 3: + matrix.setCount(readInt()); + break; + case 4: + matrix.setTotalTime(readLong()); + break; + case 5: + matrix.setUrl(readString()); + break; + case 33: + if (_type == 1) { + Ratio ratio = new Ratio(); + + visitRatio(ratio); + m_linker.onRatio(matrix, ratio); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Ratio ratio = new Ratio(); + + visitRatio(ratio); + m_linker.onRatio(matrix, ratio); + } + } + break; + } + } + + @Override + public void visitMatrixReport(MatrixReport matrixReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitMatrixReportChildren(matrixReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMatrixReportChildren(MatrixReport matrixReport, int _field, int _type) { + switch (_field) { + case 1: + matrixReport.setDomain(readString()); + break; + case 2: + matrixReport.setStartTime(readDate()); + break; + case 3: + matrixReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + matrixReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + matrixReport.addDomain(readString()); + } + } + break; + case 33: + if (_type == 1) { + Matrix matrix = new Matrix(); + + visitMatrix(matrix); + m_linker.onMatrix(matrixReport, matrix); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Matrix matrix = new Matrix(); + + visitMatrix(matrix); + m_linker.onMatrix(matrixReport, matrix); + } + } + break; + } + } + + @Override + public void visitRatio(Ratio ratio) { + byte tag; + + while ((tag = readTag()) != -1) { + visitRatioChildren(ratio, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitRatioChildren(Ratio ratio, int _field, int _type) { + switch (_field) { + case 1: + ratio.setType(readString()); + break; + case 2: + ratio.setMin(readInt()); + break; + case 3: + ratio.setMax(readInt()); + break; + case 4: + ratio.setTotalCount(readInt()); + break; + case 5: + ratio.setTotalTime(readLong()); + break; + case 6: + ratio.setUrl(readString()); + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..3c536161b4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxMaker.java @@ -0,0 +1,145 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_MAX; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_MIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TOTALTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_URL; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultSaxMaker implements IMaker { + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Matrix buildMatrix(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String name = attributes.getValue(ATTR_NAME); + String count = attributes.getValue(ATTR_COUNT); + String totalTime = attributes.getValue(ATTR_TOTALTIME); + String url = attributes.getValue(ATTR_URL); + Matrix matrix = new Matrix(name); + + if (type != null) { + matrix.setType(type); + } + + if (count != null) { + matrix.setCount(convert(Integer.class, count, 0)); + } + + if (totalTime != null) { + matrix.setTotalTime(convert(Long.class, totalTime, 0L)); + } + + if (url != null) { + matrix.setUrl(url); + } + + return matrix; + } + + @Override + public MatrixReport buildMatrixReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + MatrixReport matrixReport = new MatrixReport(domain); + + if (startTime != null) { + matrixReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + matrixReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return matrixReport; + } + + @Override + public Ratio buildRatio(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String min = attributes.getValue(ATTR_MIN); + String max = attributes.getValue(ATTR_MAX); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String totalTime = attributes.getValue(ATTR_TOTALTIME); + String url = attributes.getValue(ATTR_URL); + Ratio ratio = new Ratio(type); + + if (min != null) { + ratio.setMin(convert(Integer.class, min, 0)); + } + + if (max != null) { + ratio.setMax(convert(Integer.class, max, 0)); + } + + if (totalCount != null) { + ratio.setTotalCount(convert(Integer.class, totalCount, 0)); + } + + if (totalTime != null) { + ratio.setTotalTime(convert(Long.class, totalTime, 0L)); + } + + if (url != null) { + ratio.setUrl(url); + } + + return ratio; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..05af4f41e1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultSaxParser.java @@ -0,0 +1,270 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import static com.dianping.cat.consumer.matrix.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ELEMENT_DOMAIN_NAMES; + +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX_REPORT; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_RATIO; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.matrix.model.IEntity; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static MatrixReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(MatrixReport.class, new InputSource(removeBOM(in))); + } + + public static MatrixReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(MatrixReport.class, new InputSource(removeBOM(reader))); + } + + public static MatrixReport parse(String xml) throws SAXException, IOException { + return parseEntity(MatrixReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof MatrixReport) { + MatrixReport matrixReport = (MatrixReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + matrixReport.addDomain(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForMatrix(Matrix parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_RATIO.equals(qName)) { + Ratio ratio = m_maker.buildRatio(attributes); + + m_linker.onRatio(parentObj, ratio); + m_objs.push(ratio); + } else { + throw new SAXException(String.format("Element(%s) is not expected under matrix!", qName)); + } + + m_tags.push(qName); + } + + private void parseForMatrixReport(MatrixReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MATRIX.equals(qName)) { + Matrix matrix = m_maker.buildMatrix(attributes); + + m_linker.onMatrix(parentObj, matrix); + m_objs.push(matrix); + } else { + throw new SAXException(String.format("Element(%s) is not expected under matrix-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForRatio(Ratio parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_MATRIX_REPORT.equals(qName)) { + MatrixReport matrixReport = m_maker.buildMatrixReport(attributes); + + m_entity = matrixReport; + m_objs.push(matrixReport); + m_tags.push(qName); + } else if (ENTITY_MATRIX.equals(qName)) { + Matrix matrix = m_maker.buildMatrix(attributes); + + m_entity = matrix; + m_objs.push(matrix); + m_tags.push(qName); + } else if (ENTITY_RATIO.equals(qName)) { + Ratio ratio = m_maker.buildRatio(attributes); + + m_entity = ratio; + m_objs.push(ratio); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof MatrixReport) { + parseForMatrixReport((MatrixReport) parent, tag, qName, attributes); + } else if (parent instanceof Matrix) { + parseForMatrix((Matrix) parent, tag, qName, attributes); + } else if (parent instanceof Ratio) { + parseForRatio((Ratio) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..978044612b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,295 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_MAX; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_MIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TOTALTIME; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.matrix.model.Constants.ATTR_URL; +import static com.dianping.cat.consumer.matrix.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_MATRIX_REPORT; +import static com.dianping.cat.consumer.matrix.model.Constants.ENTITY_RATIO; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.matrix.model.IEntity; +import com.dianping.cat.consumer.matrix.model.IVisitor; +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + @Override + public void visitMatrix(Matrix matrix) { + startTag(ENTITY_MATRIX, null, ATTR_TYPE, matrix.getType(), ATTR_NAME, matrix.getName(), ATTR_COUNT, matrix.getCount(), ATTR_TOTALTIME, matrix.getTotalTime(), ATTR_URL, matrix.getUrl()); + + if (!matrix.getRatios().isEmpty()) { + for (Ratio ratio : matrix.getRatios().values()) { + ratio.accept(m_visitor); + } + } + + endTag(ENTITY_MATRIX); + } + + @Override + public void visitMatrixReport(MatrixReport matrixReport) { + startTag(ENTITY_MATRIX_REPORT, null, ATTR_DOMAIN, matrixReport.getDomain(), ATTR_STARTTIME, toString(matrixReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(matrixReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!matrixReport.getDomainNames().isEmpty()) { + for (String domain : matrixReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!matrixReport.getMatrixs().isEmpty()) { + for (Matrix matrix : matrixReport.getMatrixs().values()) { + matrix.accept(m_visitor); + } + } + + endTag(ENTITY_MATRIX_REPORT); + } + + @Override + public void visitRatio(Ratio ratio) { + startTag(ENTITY_RATIO, true, null, ATTR_TYPE, ratio.getType(), ATTR_MIN, ratio.getMin(), ATTR_MAX, ratio.getMax(), ATTR_TOTALCOUNT, ratio.getTotalCount(), ATTR_TOTALTIME, ratio.getTotalTime(), ATTR_URL, ratio.getUrl()); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/ILinker.java new file mode 100644 index 0000000000..a065652e71 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public interface ILinker { + + public boolean onMatrix(MatrixReport parent, Matrix matrix); + + public boolean onRatio(Matrix parent, Ratio ratio); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IMaker.java new file mode 100644 index 0000000000..7950c9d8da --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IMaker.java @@ -0,0 +1,16 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public interface IMaker { + + public String buildDomain(T node); + + public Matrix buildMatrix(T node); + + public MatrixReport buildMatrixReport(T node); + + public Ratio buildRatio(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IParser.java new file mode 100644 index 0000000000..97c8adfdf5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/matrix/model/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.consumer.matrix.model.transform; + +import com.dianping.cat.consumer.matrix.model.entity.Matrix; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; +import com.dianping.cat.consumer.matrix.model.entity.Ratio; + +public interface IParser { + public MatrixReport parse(IMaker maker, ILinker linker, T node); + + public void parseForMatrix(IMaker maker, ILinker linker, Matrix parent, T node); + + public void parseForRatio(IMaker maker, ILinker linker, Ratio parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/DefaultProblemHandler.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/DefaultProblemHandler.java index 296e48c5a6..53d6a7791b 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/DefaultProblemHandler.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/DefaultProblemHandler.java @@ -18,14 +18,11 @@ */ package com.dianping.cat.consumer.problem; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import org.unidal.helper.Splitters; -import org.unidal.lookup.annotation.Inject; - -import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.problem.model.entity.Entity; import com.dianping.cat.consumer.problem.model.entity.Machine; import com.dianping.cat.message.Event; @@ -37,10 +34,6 @@ public class DefaultProblemHandler extends ProblemHandler { public static final String ID = "default-problem"; - @Inject - private ServerConfigManager m_configManager; - - @Inject private Set m_errorTypes; @Override @@ -102,7 +95,7 @@ private void processTransaction(Machine machine, Transaction transaction, Messag } public void setErrorType(String type) { - m_errorTypes = new HashSet(Splitters.by(',').noEmptyItem().split(type)); + m_errorTypes = Stream.of(type.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toSet()); } -} \ No newline at end of file +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/LongExecutionProblemHandler.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/LongExecutionProblemHandler.java index c5b86f1852..3ae1b47fd0 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/LongExecutionProblemHandler.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/LongExecutionProblemHandler.java @@ -22,9 +22,8 @@ import java.util.List; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.annotation.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.configuration.server.entity.Domain; @@ -34,10 +33,11 @@ import com.dianping.cat.message.Transaction; import com.dianping.cat.message.spi.MessageTree; -public class LongExecutionProblemHandler extends ProblemHandler implements Initializable { +public class LongExecutionProblemHandler extends ProblemHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(LongExecutionProblemHandler.class); + public static final String ID = "long-execution"; - @Inject private ServerConfigManager m_configManager; private int[] m_defaultLongServiceDuration = { 50, 100, 500, 1000, 3000, 5000 }; @@ -60,6 +60,8 @@ public class LongExecutionProblemHandler extends ProblemHandler implements Initi private Map m_longCacheThresholds = new HashMap(); + private volatile boolean m_initialized; + public int computeLongDuration(long duration, String domain, int[] defaultLongDuration, Map longThresholds) { int[] messageDuration = defaultLongDuration; @@ -81,6 +83,8 @@ public int computeLongDuration(long duration, String domain, int[] defaultLongDu @Override public void handle(Machine machine, MessageTree tree) { + ensureInitialized(); + Message message = tree.getMessage(); if (message instanceof Transaction) { @@ -90,10 +94,27 @@ public void handle(Machine machine, MessageTree tree) { } } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + if (m_configManager == null) { + LOGGER.warn("Server config manager is not configured for long execution problem handler."); + m_initialized = true; + return; + } Map domains = m_configManager.getLongConfigDomains(); + m_longServiceThresholds.clear(); + m_longUrlThresholds.clear(); + m_longSqlThresholds.clear(); + for (Domain domain : domains.values()) { Integer serviceThreshold = domain.getServiceThreshold(); Integer urlThreshold = domain.getUrlThreshold(); @@ -109,6 +130,7 @@ public void initialize() throws InitializationException { m_longSqlThresholds.put(domain.getName(), sqlThreshold); } } + m_initialized = true; } private void processLongCache(Machine machine, Transaction transaction, MessageTree tree) { @@ -205,4 +227,8 @@ private void processTransaction(Machine machine, Transaction transaction, Messag } } + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemAnalyzer.java index cb20b650a3..3e4a66d312 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemAnalyzer.java @@ -18,83 +18,116 @@ */ package com.dianping.cat.consumer.problem; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.problem.model.entity.Machine; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; -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.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + ProblemAnalyzer.ID) +@Scope("prototype") +public class ProblemAnalyzer extends AbstractMessageAnalyzer { + private static final Logger LOGGER = LoggerFactory.getLogger(ProblemAnalyzer.class); -@Named(type = MessageAnalyzer.class, value = ProblemAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class ProblemAnalyzer extends AbstractMessageAnalyzer implements LogEnabled, Initializable { public static final String ID = "problem"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = ProblemAnalyzer.ID + "ReportManager") + private ReportManager problemReportManager; + + @Resource(name = "problemHandlers") + private List problemHandlers; - @Inject - private List m_handlers; + private volatile boolean initialized; @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + problemReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + problemReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - public Set getDomains() { - return m_reportManager.getDomains(getStartTime()); + return problemReportManager.getDomains(getStartTime()); } @Override public ProblemReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), domain, false); + return problemReportManager.getHourlyReport(getStartTime(), domain, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return problemReportManager; } - @Override - public void initialize() throws InitializationException { - // to work around a performance issue within plexus - m_handlers = new ArrayList(m_handlers); + private void ensureInitialized() { + if (!initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (initialized) { + return; + } + if (problemHandlers == null) { + problemHandlers = Collections.emptyList(); + LOGGER.warn("Problem analyzer has no configured handlers, keep empty handler list."); + } else { + // Copy the container-provided list before it is read on the hot path. + problemHandlers = new ArrayList(problemHandlers); + } + initialized = true; } protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + problemReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override public void process(MessageTree tree) { + ensureInitialized(); + String domain = tree.getDomain(); - ProblemReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + ProblemReport report = problemReportManager.getHourlyReport(getStartTime(), domain, true); report.addIp(tree.getIpAddress()); Machine machine = report.findOrCreateMachine(tree.getIpAddress()); - for (ProblemHandler handler : m_handlers) { + for (ProblemHandler handler : problemHandlers) { handler.handle(machine, tree); } } + public void setHandlers(List handlers) { + problemHandlers = handlers; + } + + public void setReportManager(ReportManager reportManager) { + problemReportManager = reportManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemDelegate.java index cae4f462cf..0952679fd7 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/ProblemDelegate.java @@ -27,20 +27,15 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; import java.util.Map.Entry; -@Named(type = ReportDelegate.class, value = ProblemAnalyzer.ID) public class ProblemDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_configManager; @Override @@ -115,4 +110,12 @@ public ProblemReport parseBinary(byte[] bytes) { public ProblemReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager configManager) { + m_configManager = configManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/BaseEntity.java new file mode 100644 index 0000000000..f920984290 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.problem.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.problem.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/Constants.java new file mode 100644 index 0000000000..eb65ce04e3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/Constants.java @@ -0,0 +1,70 @@ +package com.dianping.cat.consumer.problem.model; + +public class Constants { + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_DURATION = "duration"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_FAILS = "fails"; + + public static final String ATTR_GROUP_NAME = "group-name"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_STATUS = "status"; + + public static final String ATTR_TYPE = "type"; + + public static final String ATTR_VALUE = "value"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ELEMENT_MESSAGE = "message"; + + public static final String ELEMENT_MESSAGES = "messages"; + + public static final String ENTITY_DURATION = "duration"; + + public static final String ENTITY_DURATIONS = "durations"; + + public static final String ENTITY_ENTITY = "entity"; + + public static final String ENTITY_ENTITIES = "entities"; + + public static final String ENTITY_ENTRY = "entry"; + + public static final String ENTITY_ENTRIES = "entries"; + + public static final String ENTITY_GRAPH_TREND = "graph-trend"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_PROBLEM_REPORT = "problem-report"; + + public static final String ENTITY_SEGMENT = "segment"; + + public static final String ENTITY_SEGMENTS = "segments"; + + public static final String ENTITY_THREAD = "thread"; + + public static final String ENTITY_THREADS = "threads"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IEntity.java new file mode 100644 index 0000000000..3086fb30d5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.problem.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IVisitor.java new file mode 100644 index 0000000000..5ea090500a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/IVisitor.java @@ -0,0 +1,29 @@ +package com.dianping.cat.consumer.problem.model; + +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public interface IVisitor { + + public void visitDuration(Duration duration); + + public void visitEntity(Entity entity); + + public void visitEntry(Entry entry); + + public void visitGraphTrend(GraphTrend graphTrend); + + public void visitMachine(Machine machine); + + public void visitProblemReport(ProblemReport problemReport); + + public void visitSegment(Segment segment); + + public void visitThread(JavaThread thread); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Duration.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Duration.java new file mode 100644 index 0000000000..972df15a62 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Duration.java @@ -0,0 +1,99 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_DURATION; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class Duration extends BaseEntity { + private int m_value; + + private int m_count; + + private List m_messages = new ArrayList(); + + public Duration() { + } + + public Duration(int value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDuration(this); + } + + public Duration addMessage(String message) { + m_messages.add(message); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Duration) { + Duration _o = (Duration) obj; + + if (getValue() != _o.getValue()) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public List getMessages() { + return m_messages; + } + + public int getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_value; + + return hash; + } + + public Duration incCount() { + m_count++; + return this; + } + + public Duration incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Duration other) { + assertAttributeEquals(other, ENTITY_DURATION, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + } + + public Duration setCount(int count) { + m_count = count; + return this; + } + + public Duration setValue(int value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entity.java new file mode 100644 index 0000000000..eaba08c008 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entity.java @@ -0,0 +1,178 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_ENTITY; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class Entity extends BaseEntity { + private String m_id; + + private String m_type; + + private String m_status; + + private Map m_threads = new LinkedHashMap(); + + private Map m_durations = new LinkedHashMap(); + + private GraphTrend m_graphTrend; + + public Entity() { + } + + public Entity(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitEntity(this); + } + + public Entity addDuration(Duration duration) { + m_durations.put(duration.getValue(), duration); + return this; + } + + public Entity addThread(JavaThread thread) { + m_threads.put(thread.getId(), thread); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Entity) { + Entity _o = (Entity) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Duration findDuration(int value) { + return m_durations.get(value); + } + + public JavaThread findThread(String id) { + return m_threads.get(id); + } + + public Duration findOrCreateDuration(int value) { + Duration duration = m_durations.get(value); + + if (duration == null) { + synchronized (m_durations) { + duration = m_durations.get(value); + + if (duration == null) { + duration = new Duration(value); + m_durations.put(value, duration); + } + } + } + + return duration; + } + + public JavaThread findOrCreateThread(String id) { + JavaThread thread = m_threads.get(id); + + if (thread == null) { + synchronized (m_threads) { + thread = m_threads.get(id); + + if (thread == null) { + thread = new JavaThread(id); + m_threads.put(id, thread); + } + } + } + + return thread; + } + + public Map getDurations() { + return m_durations; + } + + public GraphTrend getGraphTrend() { + return m_graphTrend; + } + + public String getId() { + return m_id; + } + + public String getStatus() { + return m_status; + } + + public Map getThreads() { + return m_threads; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Entity other) { + assertAttributeEquals(other, ENTITY_ENTITY, ATTR_ID, m_id, other.getId()); + + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getStatus() != null) { + m_status = other.getStatus(); + } + } + + public Duration removeDuration(int value) { + return m_durations.remove(value); + } + + public JavaThread removeThread(String id) { + return m_threads.remove(id); + } + + public Entity setGraphTrend(GraphTrend graphTrend) { + m_graphTrend = graphTrend; + return this; + } + + public Entity setId(String id) { + m_id = id; + return this; + } + + public Entity setStatus(String status) { + m_status = status; + return this; + } + + public Entity setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entry.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entry.java new file mode 100644 index 0000000000..d9521b8a57 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Entry.java @@ -0,0 +1,163 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class Entry extends BaseEntity { + private String m_type; + + private String m_status; + + private Map m_durations = new LinkedHashMap(); + + private Map m_threads = new LinkedHashMap(); + + public Entry() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitEntry(this); + } + + public Entry addDuration(Duration duration) { + m_durations.put(duration.getValue(), duration); + return this; + } + + public Entry addThread(JavaThread thread) { + m_threads.put(thread.getId(), thread); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Entry) { + Entry _o = (Entry) obj; + + if (!equals(getType(), _o.getType())) { + return false; + } + + if (!equals(getStatus(), _o.getStatus())) { + return false; + } + + if (!equals(getDurations(), _o.getDurations())) { + return false; + } + + if (!equals(getThreads(), _o.getThreads())) { + return false; + } + + + return true; + } + + return false; + } + + public Duration findDuration(int value) { + return m_durations.get(value); + } + + public JavaThread findThread(String id) { + return m_threads.get(id); + } + + public Duration findOrCreateDuration(int value) { + Duration duration = m_durations.get(value); + + if (duration == null) { + synchronized (m_durations) { + duration = m_durations.get(value); + + if (duration == null) { + duration = new Duration(value); + m_durations.put(value, duration); + } + } + } + + return duration; + } + + public JavaThread findOrCreateThread(String id) { + JavaThread thread = m_threads.get(id); + + if (thread == null) { + synchronized (m_threads) { + thread = m_threads.get(id); + + if (thread == null) { + thread = new JavaThread(id); + m_threads.put(id, thread); + } + } + } + + return thread; + } + + public Map getDurations() { + return m_durations; + } + + public String getStatus() { + return m_status; + } + + public Map getThreads() { + return m_threads; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_type == null ? 0 : m_type.hashCode()); + hash = hash * 31 + (m_status == null ? 0 : m_status.hashCode()); + hash = hash * 31 + (m_durations == null ? 0 : m_durations.hashCode()); + hash = hash * 31 + (m_threads == null ? 0 : m_threads.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Entry other) { + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getStatus() != null) { + m_status = other.getStatus(); + } + } + + public Duration removeDuration(int value) { + return m_durations.remove(value); + } + + public JavaThread removeThread(String id) { + return m_threads.remove(id); + } + + public Entry setStatus(String status) { + m_status = status; + return this; + } + + public Entry setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/GraphTrend.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/GraphTrend.java new file mode 100644 index 0000000000..dcd6de047d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/GraphTrend.java @@ -0,0 +1,75 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_GRAPH_TREND; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class GraphTrend extends BaseEntity { + private int m_duration; + + private String m_fails; + + public GraphTrend() { + } + + public GraphTrend(int duration) { + m_duration = duration; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGraphTrend(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof GraphTrend) { + GraphTrend _o = (GraphTrend) obj; + + if (getDuration() != _o.getDuration()) { + return false; + } + + return true; + } + + return false; + } + + public int getDuration() { + return m_duration; + } + + public String getFails() { + return m_fails; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_duration; + + return hash; + } + + @Override + public void mergeAttributes(GraphTrend other) { + assertAttributeEquals(other, ENTITY_GRAPH_TREND, ATTR_DURATION, m_duration, other.getDuration()); + + m_fails = other.getFails(); + } + + public GraphTrend setDuration(int duration) { + m_duration = duration; + return this; + } + + public GraphTrend setFails(String fails) { + m_fails = fails; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/JavaThread.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/JavaThread.java new file mode 100644 index 0000000000..02b13e7a3e --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/JavaThread.java @@ -0,0 +1,131 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_THREAD; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class JavaThread extends BaseEntity { + private String m_groupName; + + private String m_name; + + private String m_id; + + private Map m_segments = new LinkedHashMap(); + + public JavaThread() { + } + + public JavaThread(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitThread(this); + } + + public JavaThread addSegment(Segment segment) { + m_segments.put(segment.getId(), segment); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof JavaThread) { + JavaThread _o = (JavaThread) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Segment findSegment(Integer id) { + return m_segments.get(id); + } + + public Segment findOrCreateSegment(Integer id) { + Segment segment = m_segments.get(id); + + if (segment == null) { + synchronized (m_segments) { + segment = m_segments.get(id); + + if (segment == null) { + segment = new Segment(id); + m_segments.put(id, segment); + } + } + } + + return segment; + } + + public String getGroupName() { + return m_groupName; + } + + public String getId() { + return m_id; + } + + public String getName() { + return m_name; + } + + public Map getSegments() { + return m_segments; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(JavaThread other) { + assertAttributeEquals(other, ENTITY_THREAD, ATTR_ID, m_id, other.getId()); + + if (other.getGroupName() != null) { + m_groupName = other.getGroupName(); + } + + if (other.getName() != null) { + m_name = other.getName(); + } + } + + public Segment removeSegment(Integer id) { + return m_segments.remove(id); + } + + public JavaThread setGroupName(String groupName) { + m_groupName = groupName; + return this; + } + + public JavaThread setId(String id) { + m_id = id; + return this; + } + + public JavaThread setName(String name) { + m_name = name; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Machine.java new file mode 100644 index 0000000000..87e7853099 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Machine.java @@ -0,0 +1,115 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_MACHINE; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_ip; + + private List m_entries = new ArrayList(); + + private Map m_entities = new LinkedHashMap(); + + public Machine() { + } + + public Machine(String ip) { + m_ip = ip; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addEntity(Entity entity) { + m_entities.put(entity.getId(), entity); + return this; + } + + public Machine addEntry(Entry entry) { + m_entries.add(entry); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getIp(), _o.getIp())) { + return false; + } + + return true; + } + + return false; + } + + public Entity findEntity(String id) { + return m_entities.get(id); + } + + public Entity findOrCreateEntity(String id) { + Entity entity = m_entities.get(id); + + if (entity == null) { + synchronized (m_entities) { + entity = m_entities.get(id); + + if (entity == null) { + entity = new Entity(id); + m_entities.put(id, entity); + } + } + } + + return entity; + } + + public Map getEntities() { + return m_entities; + } + + public List getEntries() { + return m_entries; + } + + public String getIp() { + return m_ip; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_ip == null ? 0 : m_ip.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_IP, m_ip, other.getIp()); + + } + + public Entity removeEntity(String id) { + return m_entities.remove(id); + } + + public Machine setIp(String ip) { + m_ip = ip; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/ProblemReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/ProblemReport.java new file mode 100644 index 0000000000..f6f00fee8d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/ProblemReport.java @@ -0,0 +1,155 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_PROBLEM_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class ProblemReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_machines = new LinkedHashMap(); + + private Set m_domainNames = new LinkedHashSet(); + + private Set m_ips = new LinkedHashSet(); + + public ProblemReport() { + } + + public ProblemReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitProblemReport(this); + } + + public ProblemReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public ProblemReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public ProblemReport addMachine(Machine machine) { + m_machines.put(machine.getIp(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ProblemReport) { + ProblemReport _o = (ProblemReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String ip) { + return m_machines.get(ip); + } + + public Machine findOrCreateMachine(String ip) { + Machine machine = m_machines.get(ip); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(ip); + + if (machine == null) { + machine = new Machine(ip); + m_machines.put(ip, machine); + } + } + } + + return machine; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Set getIps() { + return m_ips; + } + + public Map getMachines() { + return m_machines; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ProblemReport other) { + assertAttributeEquals(other, ENTITY_PROBLEM_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String ip) { + return m_machines.remove(ip); + } + + public ProblemReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public ProblemReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public ProblemReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Segment.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Segment.java new file mode 100644 index 0000000000..b4f625116f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/entity/Segment.java @@ -0,0 +1,99 @@ +package com.dianping.cat.consumer.problem.model.entity; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_SEGMENT; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.consumer.problem.model.BaseEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; + +public class Segment extends BaseEntity { + private Integer m_id; + + private int m_count; + + private List m_messages = new ArrayList(); + + public Segment() { + } + + public Segment(Integer id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSegment(this); + } + + public Segment addMessage(String message) { + m_messages.add(message); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Segment) { + Segment _o = (Segment) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public Integer getId() { + return m_id; + } + + public List getMessages() { + return m_messages; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Segment incCount() { + m_count++; + return this; + } + + public Segment incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Segment other) { + assertAttributeEquals(other, ENTITY_SEGMENT, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + } + + public Segment setCount(int count) { + m_count = count; + return this; + } + + public Segment setId(Integer id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..df5b3cb799 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/BaseVisitor.java @@ -0,0 +1,76 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import com.dianping.cat.consumer.problem.model.IVisitor; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDuration(Duration duration) { + } + + @Override + public void visitEntity(Entity entity) { + for (JavaThread thread : entity.getThreads().values()) { + visitThread(thread); + } + + for (Duration duration : entity.getDurations().values()) { + visitDuration(duration); + } + + if (entity.getGraphTrend() != null) { + visitGraphTrend(entity.getGraphTrend()); + } + } + + @Override + public void visitEntry(Entry entry) { + for (Duration duration : entry.getDurations().values()) { + visitDuration(duration); + } + + for (JavaThread thread : entry.getThreads().values()) { + visitThread(thread); + } + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + } + + @Override + public void visitMachine(Machine machine) { + for (Entry entry : machine.getEntries()) { + visitEntry(entry); + } + + for (Entity entity : machine.getEntities().values()) { + visitEntity(entity); + } + } + + @Override + public void visitProblemReport(ProblemReport problemReport) { + for (Machine machine : problemReport.getMachines().values()) { + visitMachine(machine); + } + } + + @Override + public void visitSegment(Segment segment) { + } + + @Override + public void visitThread(JavaThread thread) { + for (Segment segment : thread.getSegments().values()) { + visitSegment(segment); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..1987dcac9a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultLinker.java @@ -0,0 +1,152 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDuration(final Entry parent, final Duration duration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDuration(duration); + } + }); + } else { + parent.addDuration(duration); + } + + return true; + } + + @Override + public boolean onDuration(final Entity parent, final Duration duration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDuration(duration); + } + }); + } else { + parent.addDuration(duration); + } + + return true; + } + + @Override + public boolean onEntity(final Machine parent, final Entity entity) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addEntity(entity); + } + }); + } else { + parent.addEntity(entity); + } + + return true; + } + + @Override + public boolean onEntry(final Machine parent, final Entry entry) { + parent.addEntry(entry); + return true; + } + + @Override + public boolean onGraphTrend(final Entity parent, final GraphTrend graphTrend) { + parent.setGraphTrend(graphTrend); + return true; + } + + @Override + public boolean onMachine(final ProblemReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onSegment(final JavaThread parent, final Segment segment) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSegment(segment); + } + }); + } else { + parent.addSegment(segment); + } + + return true; + } + + @Override + public boolean onThread(final Entry parent, final JavaThread thread) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addThread(thread); + } + }); + } else { + parent.addThread(thread); + } + + return true; + } + + @Override + public boolean onThread(final Entity parent, final JavaThread thread) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addThread(thread); + } + }); + } else { + parent.addThread(thread); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..b37b24991a --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultMerger.java @@ -0,0 +1,281 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.problem.model.IEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private ProblemReport m_problemReport; + + public DefaultMerger() { + } + + public DefaultMerger(ProblemReport problemReport) { + m_problemReport = problemReport; + m_objs.push(problemReport); + } + + public ProblemReport getProblemReport() { + return m_problemReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDuration(Duration to, Duration from) { + to.mergeAttributes(from); + to.getMessages().addAll(from.getMessages()); + } + + protected void mergeEntity(Entity to, Entity from) { + to.mergeAttributes(from); + } + + protected void mergeEntry(Entry to, Entry from) { + to.mergeAttributes(from); + } + + protected void mergeGraphTrend(GraphTrend to, GraphTrend from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeProblemReport(ProblemReport to, ProblemReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + to.getIps().addAll(from.getIps()); + } + + protected void mergeSegment(Segment to, Segment from) { + to.mergeAttributes(from); + to.getMessages().addAll(from.getMessages()); + } + + protected void mergeThread(JavaThread to, JavaThread from) { + to.mergeAttributes(from); + } + + @Override + public void visitDuration(Duration from) { + Duration to = (Duration) m_objs.peek(); + + mergeDuration(to, from); + visitDurationChildren(to, from); + } + + protected void visitDurationChildren(Duration to, Duration from) { + } + + @Override + public void visitEntity(Entity from) { + Entity to = (Entity) m_objs.peek(); + + mergeEntity(to, from); + visitEntityChildren(to, from); + } + + protected void visitEntityChildren(Entity to, Entity from) { + for (JavaThread source : from.getThreads().values()) { + JavaThread target = to.findThread(source.getId()); + + if (target == null) { + target = new JavaThread(source.getId()); + to.addThread(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Duration source : from.getDurations().values()) { + Duration target = to.findDuration(source.getValue()); + + if (target == null) { + target = new Duration(source.getValue()); + to.addDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getGraphTrend() != null) { + GraphTrend target = to.getGraphTrend(); + + if (target == null) { + GraphTrend source = from.getGraphTrend(); + + target = new GraphTrend(source.getDuration()); + to.setGraphTrend(target); + } + + m_objs.push(target); + from.getGraphTrend().accept(this); + m_objs.pop(); + } + } + + @Override + public void visitEntry(Entry from) { + Entry to = (Entry) m_objs.peek(); + + mergeEntry(to, from); + visitEntryChildren(to, from); + } + + protected void visitEntryChildren(Entry to, Entry from) { + for (Duration source : from.getDurations().values()) { + Duration target = to.findDuration(source.getValue()); + + if (target == null) { + target = new Duration(source.getValue()); + to.addDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (JavaThread source : from.getThreads().values()) { + JavaThread target = to.findThread(source.getId()); + + if (target == null) { + target = new JavaThread(source.getId()); + to.addThread(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitGraphTrend(GraphTrend from) { + GraphTrend to = (GraphTrend) m_objs.peek(); + + mergeGraphTrend(to, from); + visitGraphTrendChildren(to, from); + } + + protected void visitGraphTrendChildren(GraphTrend to, GraphTrend from) { + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (Entry source : from.getEntries()) { + Entry target = null; + + if (target == null) { + target = new Entry(); + to.addEntry(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Entity source : from.getEntities().values()) { + Entity target = to.findEntity(source.getId()); + + if (target == null) { + target = new Entity(source.getId()); + to.addEntity(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitProblemReport(ProblemReport from) { + ProblemReport to = (ProblemReport) m_objs.peek(); + + mergeProblemReport(to, from); + visitProblemReportChildren(to, from); + } + + protected void visitProblemReportChildren(ProblemReport to, ProblemReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getIp()); + + if (target == null) { + target = new Machine(source.getIp()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitSegment(Segment from) { + Segment to = (Segment) m_objs.peek(); + + mergeSegment(to, from); + visitSegmentChildren(to, from); + } + + protected void visitSegmentChildren(Segment to, Segment from) { + } + + @Override + public void visitThread(JavaThread from) { + JavaThread to = (JavaThread) m_objs.peek(); + + mergeThread(to, from); + visitThreadChildren(to, from); + } + + protected void visitThreadChildren(JavaThread to, JavaThread from) { + for (Segment source : from.getSegments().values()) { + Segment target = to.findSegment(source.getId()); + + if (target == null) { + target = new Segment(source.getId()); + to.addSegment(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..de7f6f0706 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,322 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.problem.model.IVisitor; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(ProblemReport problemReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(problemReport, out); + return out.toByteArray(); + } + + public static void build(ProblemReport problemReport, OutputStream out) { + problemReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDuration(Duration duration) { + writeTag(1, 0); + writeInt(duration.getValue()); + + writeTag(2, 0); + writeInt(duration.getCount()); + + if (duration.getMessages() != null) { + writeTag(3, 2); + writeInt(duration.getMessages().size()); + + for (String message : duration.getMessages()) { + writeString(message); + } + } + + writeTag(63, 3); + } + + @Override + public void visitEntity(Entity entity) { + if (entity.getId() != null) { + writeTag(1, 1); + writeString(entity.getId()); + } + + if (entity.getType() != null) { + writeTag(2, 1); + writeString(entity.getType()); + } + + if (entity.getStatus() != null) { + writeTag(3, 1); + writeString(entity.getStatus()); + } + + if (!entity.getThreads().isEmpty()) { + writeTag(33, 2); + writeInt(entity.getThreads().size()); + + for (JavaThread thread : entity.getThreads().values()) { + thread.accept(m_visitor); + } + } + + if (!entity.getDurations().isEmpty()) { + writeTag(34, 2); + writeInt(entity.getDurations().size()); + + for (Duration duration : entity.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (entity.getGraphTrend() != null) { + writeTag(35, 1); + entity.getGraphTrend().accept(m_visitor); + } + + writeTag(63, 3); + } + + @Override + public void visitEntry(Entry entry) { + if (entry.getType() != null) { + writeTag(1, 1); + writeString(entry.getType()); + } + + if (entry.getStatus() != null) { + writeTag(2, 1); + writeString(entry.getStatus()); + } + + if (!entry.getDurations().isEmpty()) { + writeTag(33, 2); + writeInt(entry.getDurations().size()); + + for (Duration duration : entry.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (!entry.getThreads().isEmpty()) { + writeTag(34, 2); + writeInt(entry.getThreads().size()); + + for (JavaThread thread : entry.getThreads().values()) { + thread.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + writeTag(1, 0); + writeInt(graphTrend.getDuration()); + + writeTag(2, 0); + writeString(graphTrend.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getIp() != null) { + writeTag(1, 1); + writeString(machine.getIp()); + } + + if (!machine.getEntries().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getEntries().size()); + + for (Entry entry : machine.getEntries()) { + entry.accept(m_visitor); + } + } + + if (!machine.getEntities().isEmpty()) { + writeTag(34, 2); + writeInt(machine.getEntities().size()); + + for (Entity entity : machine.getEntities().values()) { + entity.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitProblemReport(ProblemReport problemReport) { + writeTag(63, 0); + + if (problemReport.getDomain() != null) { + writeTag(1, 1); + writeString(problemReport.getDomain()); + } + + if (problemReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(problemReport.getStartTime()); + } + + if (problemReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(problemReport.getEndTime()); + } + + if (problemReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(problemReport.getDomainNames().size()); + + for (String domain : problemReport.getDomainNames()) { + writeString(domain); + } + } + + if (problemReport.getIps() != null) { + writeTag(5, 2); + writeInt(problemReport.getIps().size()); + + for (String ip : problemReport.getIps()) { + writeString(ip); + } + } + + if (!problemReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(problemReport.getMachines().size()); + + for (Machine machine : problemReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitSegment(Segment segment) { + if (segment.getId() != null) { + writeTag(1, 1); + writeInt(segment.getId()); + } + + writeTag(2, 0); + writeInt(segment.getCount()); + + if (segment.getMessages() != null) { + writeTag(3, 2); + writeInt(segment.getMessages().size()); + + for (String message : segment.getMessages()) { + writeString(message); + } + } + + writeTag(63, 3); + } + + @Override + public void visitThread(JavaThread thread) { + if (thread.getGroupName() != null) { + writeTag(1, 1); + writeString(thread.getGroupName()); + } + + if (thread.getName() != null) { + writeTag(2, 1); + writeString(thread.getName()); + } + + if (thread.getId() != null) { + writeTag(3, 1); + writeString(thread.getId()); + } + + if (!thread.getSegments().isEmpty()) { + writeTag(33, 2); + writeInt(thread.getSegments().size()); + + for (Segment segment : thread.getSegments().values()) { + segment.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..fa82064593 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultNativeParser.java @@ -0,0 +1,429 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.problem.model.IVisitor; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static ProblemReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static ProblemReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + ProblemReport problemReport = new ProblemReport(); + + try { + problemReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return problemReport; + } + + @Override + public void visitDuration(Duration duration) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDurationChildren(duration, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDurationChildren(Duration duration, int _field, int _type) { + switch (_field) { + case 1: + duration.setValue(readInt()); + break; + case 2: + duration.setCount(readInt()); + break; + case 3: + if (_type == 1) { + duration.addMessage(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + duration.addMessage(readString()); + } + } + break; + } + } + + @Override + public void visitEntity(Entity entity) { + byte tag; + + while ((tag = readTag()) != -1) { + visitEntityChildren(entity, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitEntityChildren(Entity entity, int _field, int _type) { + switch (_field) { + case 1: + entity.setId(readString()); + break; + case 2: + entity.setType(readString()); + break; + case 3: + entity.setStatus(readString()); + break; + case 33: + if (_type == 1) { + JavaThread thread = new JavaThread(); + + visitThread(thread); + m_linker.onThread(entity, thread); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + JavaThread thread = new JavaThread(); + + visitThread(thread); + m_linker.onThread(entity, thread); + } + } + break; + case 34: + if (_type == 1) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(entity, duration); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(entity, duration); + } + } + break; + case 35: + GraphTrend graphTrend = new GraphTrend(); + + visitGraphTrend(graphTrend); + m_linker.onGraphTrend(entity, graphTrend); + break; + } + } + + @Override + public void visitEntry(Entry entry) { + byte tag; + + while ((tag = readTag()) != -1) { + visitEntryChildren(entry, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitEntryChildren(Entry entry, int _field, int _type) { + switch (_field) { + case 1: + entry.setType(readString()); + break; + case 2: + entry.setStatus(readString()); + break; + case 33: + if (_type == 1) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(entry, duration); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(entry, duration); + } + } + break; + case 34: + if (_type == 1) { + JavaThread thread = new JavaThread(); + + visitThread(thread); + m_linker.onThread(entry, thread); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + JavaThread thread = new JavaThread(); + + visitThread(thread); + m_linker.onThread(entry, thread); + } + } + break; + } + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + byte tag; + + while ((tag = readTag()) != -1) { + visitGraphTrendChildren(graphTrend, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitGraphTrendChildren(GraphTrend graphTrend, int _field, int _type) { + switch (_field) { + case 1: + graphTrend.setDuration(readInt()); + break; + case 2: + graphTrend.setFails(readString()); + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setIp(readString()); + break; + case 33: + if (_type == 1) { + Entry entry = new Entry(); + + visitEntry(entry); + m_linker.onEntry(machine, entry); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Entry entry = new Entry(); + + visitEntry(entry); + m_linker.onEntry(machine, entry); + } + } + break; + case 34: + if (_type == 1) { + Entity entity = new Entity(); + + visitEntity(entity); + m_linker.onEntity(machine, entity); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Entity entity = new Entity(); + + visitEntity(entity); + m_linker.onEntity(machine, entity); + } + } + break; + } + } + + @Override + public void visitProblemReport(ProblemReport problemReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitProblemReportChildren(problemReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitProblemReportChildren(ProblemReport problemReport, int _field, int _type) { + switch (_field) { + case 1: + problemReport.setDomain(readString()); + break; + case 2: + problemReport.setStartTime(readDate()); + break; + case 3: + problemReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + problemReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + problemReport.addDomain(readString()); + } + } + break; + case 5: + if (_type == 1) { + problemReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + problemReport.addIp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(problemReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(problemReport, machine); + } + } + break; + } + } + + @Override + public void visitSegment(Segment segment) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSegmentChildren(segment, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSegmentChildren(Segment segment, int _field, int _type) { + switch (_field) { + case 1: + segment.setId(readInt()); + break; + case 2: + segment.setCount(readInt()); + break; + case 3: + if (_type == 1) { + segment.addMessage(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + segment.addMessage(readString()); + } + } + break; + } + } + + @Override + public void visitThread(JavaThread thread) { + byte tag; + + while ((tag = readTag()) != -1) { + visitThreadChildren(thread, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitThreadChildren(JavaThread thread, int _field, int _type) { + switch (_field) { + case 1: + thread.setGroupName(readString()); + break; + case 2: + thread.setName(readString()); + break; + case 3: + thread.setId(readString()); + break; + case 33: + if (_type == 1) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(thread, segment); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(thread, segment); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..fcc8ea1566 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxMaker.java @@ -0,0 +1,201 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_GROUP_NAME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_STATUS; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_VALUE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultSaxMaker implements IMaker { + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Duration buildDuration(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + Duration duration = new Duration(value == null ? 0 : convert(Integer.class, value, 0)); + + if (count != null) { + duration.setCount(convert(Integer.class, count, 0)); + } + + return duration; + } + + @Override + public Entity buildEntity(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String type = attributes.getValue(ATTR_TYPE); + String status = attributes.getValue(ATTR_STATUS); + Entity entity = new Entity(id); + + if (type != null) { + entity.setType(type); + } + + if (status != null) { + entity.setStatus(status); + } + + return entity; + } + + @Override + public Entry buildEntry(Attributes attributes) { + String type = attributes.getValue(ATTR_TYPE); + String status = attributes.getValue(ATTR_STATUS); + Entry entry = new Entry(); + + if (type != null) { + entry.setType(type); + } + + if (status != null) { + entry.setStatus(status); + } + + return entry; + } + + @Override + public GraphTrend buildGraphTrend(Attributes attributes) { + String duration = attributes.getValue(ATTR_DURATION); + String fails = attributes.getValue(ATTR_FAILS); + GraphTrend graphTrend = new GraphTrend(duration == null ? 0 : convert(Integer.class, duration, 0)); + + if (fails != null) { + graphTrend.setFails(fails); + } + + return graphTrend; + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String ip = attributes.getValue(ATTR_IP); + Machine machine = new Machine(ip); + + return machine; + } + + @Override + public String buildMessage(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public ProblemReport buildProblemReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + ProblemReport problemReport = new ProblemReport(domain); + + if (startTime != null) { + problemReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + problemReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return problemReport; + } + + @Override + public Segment buildSegment(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + Segment segment = new Segment(id == null ? null : convert(Integer.class, id, null)); + + if (count != null) { + segment.setCount(convert(Integer.class, count, 0)); + } + + return segment; + } + + @Override + public JavaThread buildThread(Attributes attributes) { + String groupName = attributes.getValue(ATTR_GROUP_NAME); + String name = attributes.getValue(ATTR_NAME); + String id = attributes.getValue(ATTR_ID); + JavaThread thread = new JavaThread(id); + + if (groupName != null) { + thread.setGroupName(groupName); + } + + if (name != null) { + thread.setName(name); + } + + return thread; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..6ddbf39f8c --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultSaxParser.java @@ -0,0 +1,417 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_DOMAIN_NAMES; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_IPS; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_MESSAGE; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_MESSAGES; + +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_DURATION; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_ENTITY; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_ENTRY; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_PROBLEM_REPORT; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_THREAD; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.problem.model.IEntity; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static ProblemReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(ProblemReport.class, new InputSource(removeBOM(in))); + } + + public static ProblemReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(ProblemReport.class, new InputSource(removeBOM(reader))); + } + + public static ProblemReport parse(String xml) throws SAXException, IOException { + return parseEntity(ProblemReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof ProblemReport) { + ProblemReport problemReport = (ProblemReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + problemReport.addDomain(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + problemReport.addIp(getText()); + } + } else if (currentObj instanceof Segment) { + Segment segment = (Segment) currentObj; + + if (ELEMENT_MESSAGE.equals(currentTag)) { + segment.addMessage(getText()); + } + } else if (currentObj instanceof Duration) { + Duration duration = (Duration) currentObj; + + if (ELEMENT_MESSAGE.equals(currentTag)) { + duration.addMessage(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDuration(Duration parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_MESSAGES.equals(qName) || ELEMENT_MESSAGE.equals(qName)) { + m_objs.push(parentObj); + } else { + throw new SAXException(String.format("Element(%s) is not expected under duration!", qName)); + } + + m_tags.push(qName); + } + + private void parseForEntity(Entity parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_THREAD.equals(qName)) { + JavaThread thread = m_maker.buildThread(attributes); + + m_linker.onThread(parentObj, thread); + m_objs.push(thread); + } else if (ENTITY_DURATION.equals(qName)) { + Duration duration = m_maker.buildDuration(attributes); + + m_linker.onDuration(parentObj, duration); + m_objs.push(duration); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_linker.onGraphTrend(parentObj, graphTrend); + m_objs.push(graphTrend); + } else { + throw new SAXException(String.format("Element(%s) is not expected under entity!", qName)); + } + + m_tags.push(qName); + } + + private void parseForEntry(Entry parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DURATION.equals(qName)) { + Duration duration = m_maker.buildDuration(attributes); + + m_linker.onDuration(parentObj, duration); + m_objs.push(duration); + } else if (ENTITY_THREAD.equals(qName)) { + JavaThread thread = m_maker.buildThread(attributes); + + m_linker.onThread(parentObj, thread); + m_objs.push(thread); + } else { + throw new SAXException(String.format("Element(%s) is not expected under entry!", qName)); + } + + m_tags.push(qName); + } + + private void parseForGraphTrend(GraphTrend parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_ENTRY.equals(qName)) { + Entry entry = m_maker.buildEntry(attributes); + + m_linker.onEntry(parentObj, entry); + m_objs.push(entry); + } else if (ENTITY_ENTITY.equals(qName)) { + Entity entity = m_maker.buildEntity(attributes); + + m_linker.onEntity(parentObj, entity); + m_objs.push(entity); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForProblemReport(ProblemReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under problem-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSegment(Segment parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_MESSAGES.equals(qName) || ELEMENT_MESSAGE.equals(qName)) { + m_objs.push(parentObj); + } else { + throw new SAXException(String.format("Element(%s) is not expected under segment!", qName)); + } + + m_tags.push(qName); + } + + private void parseForThread(JavaThread parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_linker.onSegment(parentObj, segment); + m_objs.push(segment); + } else { + throw new SAXException(String.format("Element(%s) is not expected under thread!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_PROBLEM_REPORT.equals(qName)) { + ProblemReport problemReport = m_maker.buildProblemReport(attributes); + + m_entity = problemReport; + m_objs.push(problemReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_ENTRY.equals(qName)) { + Entry entry = m_maker.buildEntry(attributes); + + m_entity = entry; + m_objs.push(entry); + m_tags.push(qName); + } else if (ENTITY_THREAD.equals(qName)) { + JavaThread thread = m_maker.buildThread(attributes); + + m_entity = thread; + m_objs.push(thread); + m_tags.push(qName); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_entity = segment; + m_objs.push(segment); + m_tags.push(qName); + } else if (ENTITY_DURATION.equals(qName)) { + Duration duration = m_maker.buildDuration(attributes); + + m_entity = duration; + m_objs.push(duration); + m_tags.push(qName); + } else if (ENTITY_ENTITY.equals(qName)) { + Entity entity = m_maker.buildEntity(attributes); + + m_entity = entity; + m_objs.push(entity); + m_tags.push(qName); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_entity = graphTrend; + m_objs.push(graphTrend); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ProblemReport) { + parseForProblemReport((ProblemReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof Entry) { + parseForEntry((Entry) parent, tag, qName, attributes); + } else if (parent instanceof JavaThread) { + parseForThread((JavaThread) parent, tag, qName, attributes); + } else if (parent instanceof Segment) { + parseForSegment((Segment) parent, tag, qName, attributes); + } else if (parent instanceof Duration) { + parseForDuration((Duration) parent, tag, qName, attributes); + } else if (parent instanceof Entity) { + parseForEntity((Entity) parent, tag, qName, attributes); + } else if (parent instanceof GraphTrend) { + parseForGraphTrend((GraphTrend) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..91412e4335 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,402 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_GROUP_NAME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_STATUS; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.problem.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.problem.model.Constants.ELEMENT_MESSAGE; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_DURATION; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_ENTITY; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_ENTRY; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_PROBLEM_REPORT; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.problem.model.Constants.ENTITY_THREAD; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.problem.model.IEntity; +import com.dianping.cat.consumer.problem.model.IVisitor; +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + @Override + public void visitDuration(Duration duration) { + startTag(ENTITY_DURATION, null, ATTR_VALUE, duration.getValue(), ATTR_COUNT, duration.getCount()); + + if (!duration.getMessages().isEmpty()) { + for (String message : duration.getMessages()) { + tagWithText(ELEMENT_MESSAGE, message); + } + } + + endTag(ENTITY_DURATION); + } + + @Override + public void visitEntity(Entity entity) { + startTag(ENTITY_ENTITY, null, ATTR_ID, entity.getId(), ATTR_TYPE, entity.getType(), ATTR_STATUS, entity.getStatus()); + + if (!entity.getThreads().isEmpty()) { + for (JavaThread thread : entity.getThreads().values()) { + thread.accept(m_visitor); + } + } + + if (!entity.getDurations().isEmpty()) { + for (Duration duration : entity.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (entity.getGraphTrend() != null) { + entity.getGraphTrend().accept(m_visitor); + } + + endTag(ENTITY_ENTITY); + } + + @Override + public void visitEntry(Entry entry) { + startTag(ENTITY_ENTRY, null, ATTR_TYPE, entry.getType(), ATTR_STATUS, entry.getStatus()); + + if (!entry.getDurations().isEmpty()) { + for (Duration duration : entry.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (!entry.getThreads().isEmpty()) { + for (JavaThread thread : entry.getThreads().values()) { + thread.accept(m_visitor); + } + } + + endTag(ENTITY_ENTRY); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + startTag(ENTITY_GRAPH_TREND, true, null, ATTR_DURATION, graphTrend.getDuration(), ATTR_FAILS, graphTrend.getFails()); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_IP, machine.getIp()); + + if (!machine.getEntries().isEmpty()) { + for (Entry entry : machine.getEntries()) { + entry.accept(m_visitor); + } + } + + if (!machine.getEntities().isEmpty()) { + for (Entity entity : machine.getEntities().values()) { + entity.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitProblemReport(ProblemReport problemReport) { + startTag(ENTITY_PROBLEM_REPORT, null, ATTR_DOMAIN, problemReport.getDomain(), ATTR_STARTTIME, toString(problemReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(problemReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!problemReport.getDomainNames().isEmpty()) { + for (String domain : problemReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!problemReport.getIps().isEmpty()) { + for (String ip : problemReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!problemReport.getMachines().isEmpty()) { + for (Machine machine : problemReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_PROBLEM_REPORT); + } + + @Override + public void visitSegment(Segment segment) { + startTag(ENTITY_SEGMENT, null, ATTR_ID, segment.getId(), ATTR_COUNT, segment.getCount()); + + if (!segment.getMessages().isEmpty()) { + for (String message : segment.getMessages()) { + tagWithText(ELEMENT_MESSAGE, message); + } + } + + endTag(ENTITY_SEGMENT); + } + + @Override + public void visitThread(JavaThread thread) { + startTag(ENTITY_THREAD, null, ATTR_GROUP_NAME, thread.getGroupName(), ATTR_NAME, thread.getName(), ATTR_ID, thread.getId()); + + if (!thread.getSegments().isEmpty()) { + for (Segment segment : thread.getSegments().values()) { + segment.accept(m_visitor); + } + } + + endTag(ENTITY_THREAD); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/ILinker.java new file mode 100644 index 0000000000..a0dfe1cb42 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/ILinker.java @@ -0,0 +1,31 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public interface ILinker { + + public boolean onDuration(Entry parent, Duration duration); + + public boolean onDuration(Entity parent, Duration duration); + + public boolean onEntity(Machine parent, Entity entity); + + public boolean onEntry(Machine parent, Entry entry); + + public boolean onGraphTrend(Entity parent, GraphTrend graphTrend); + + public boolean onMachine(ProblemReport parent, Machine machine); + + public boolean onSegment(JavaThread parent, Segment segment); + + public boolean onThread(Entry parent, JavaThread thread); + + public boolean onThread(Entity parent, JavaThread thread); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IMaker.java new file mode 100644 index 0000000000..d3ff8efaaf --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IMaker.java @@ -0,0 +1,35 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public interface IMaker { + + public String buildDomain(T node); + + public Duration buildDuration(T node); + + public Entity buildEntity(T node); + + public Entry buildEntry(T node); + + public GraphTrend buildGraphTrend(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public String buildMessage(T node); + + public ProblemReport buildProblemReport(T node); + + public Segment buildSegment(T node); + + public JavaThread buildThread(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IParser.java new file mode 100644 index 0000000000..8a3fe9c044 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/problem/model/transform/IParser.java @@ -0,0 +1,28 @@ +package com.dianping.cat.consumer.problem.model.transform; + +import com.dianping.cat.consumer.problem.model.entity.Duration; +import com.dianping.cat.consumer.problem.model.entity.Entity; +import com.dianping.cat.consumer.problem.model.entity.Entry; +import com.dianping.cat.consumer.problem.model.entity.GraphTrend; +import com.dianping.cat.consumer.problem.model.entity.JavaThread; +import com.dianping.cat.consumer.problem.model.entity.Machine; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; +import com.dianping.cat.consumer.problem.model.entity.Segment; + +public interface IParser { + public ProblemReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDuration(IMaker maker, ILinker linker, Duration parent, T node); + + public void parseForEntity(IMaker maker, ILinker linker, Entity parent, T node); + + public void parseForEntry(IMaker maker, ILinker linker, Entry parent, T node); + + public void parseForGraphTrend(IMaker maker, ILinker linker, GraphTrend parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForSegment(IMaker maker, ILinker linker, Segment parent, T node); + + public void parseForJavaThread(IMaker maker, ILinker linker, JavaThread parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateAnalyzer.java index eca9eab543..de520b077b 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateAnalyzer.java @@ -20,7 +20,9 @@ import com.dianping.cat.Constants; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.configuration.NetworkInterfaceManager; import com.dianping.cat.consumer.state.model.entity.*; @@ -32,34 +34,34 @@ import com.dianping.cat.service.ProjectService; import com.dianping.cat.statistic.ServerStatistic.Statistic; import com.dianping.cat.statistic.ServerStatisticManager; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicLong; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = StateAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class StateAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + StateAnalyzer.ID) +@Scope("prototype") +public class StateAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "state"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = StateAnalyzer.ID + "ReportManager") + private ReportManager stateReportManager; - @Inject - private ServerStatisticManager m_serverStateManager; + @Resource(name = "serverStatisticManager") + private ServerStatisticManager serverStatisticManager; - @Inject - private ServerFilterConfigManager m_serverFilterConfigManager; + @Resource(name = "serverFilterConfigManager") + private ServerFilterConfigManager serverFilterConfigManager; - @Inject - private ProjectService m_projectService; + @Resource(name = "projectService") + private ProjectService projectService; - private String m_ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress(); + private String ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress(); private Machine buildStateInfo(Machine machine) { long minute = 1000 * 60; @@ -73,7 +75,7 @@ private Machine buildStateInfo(Machine machine) { end = current; } for (; start < end; start += minute) { - Statistic state = m_serverStateManager.findOrCreateState(start); + Statistic state = serverStatisticManager.findOrCreateState(start); Message temp = machine.findOrCreateMessage(start); Map totals = state.getMessageTotals(); Map totalLosses = state.getMessageTotalLosses(); @@ -164,13 +166,13 @@ private Machine buildStateInfo(Machine machine) { public synchronized void doCheckpoint(boolean atEnd) { long startTime = getStartTime(); StateReport stateReport = getReport(Constants.CAT); - Map reports = m_reportManager.getHourlyReports(startTime); + Map reports = stateReportManager.getHourlyReports(startTime); reports.put(Constants.CAT, stateReport); if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(startTime, StoragePolicy.FILE_AND_DB, m_index); + stateReportManager.storeHourlyReports(startTime, StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(startTime, StoragePolicy.FILE, m_index); + stateReportManager.storeHourlyReports(startTime, StoragePolicy.FILE, m_index); } if (atEnd) { long minute = 1000 * 60; @@ -178,16 +180,11 @@ public synchronized void doCheckpoint(boolean atEnd) { long end = m_startTime - minute * 60; for (; start < end; start += minute) { - m_serverStateManager.removeState(start); + serverStatisticManager.removeState(start); } } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public StateReport getReport(String domain) { StateReport report = new StateReport(Constants.CAT); @@ -195,9 +192,9 @@ public StateReport getReport(String domain) { report.setStartTime(new Date(m_startTime)); report.setEndTime(new Date(m_startTime + MINUTE * 60 - 1)); - Machine machine = buildStateInfo(report.findOrCreateMachine(m_ip)); - StateReport stateReport = m_reportManager.getHourlyReport(getStartTime(), Constants.CAT, true); - Map processDomains = stateReport.findOrCreateMachine(m_ip).getProcessDomains(); + Machine machine = buildStateInfo(report.findOrCreateMachine(ip)); + StateReport stateReport = stateReportManager.getHourlyReport(getStartTime(), Constants.CAT, true); + Map processDomains = stateReport.findOrCreateMachine(ip).getProcessDomains(); for (Map.Entry entry : machine.getProcessDomains().entrySet()) { ProcessDomain processDomain = processDomains.get(entry.getKey()); @@ -211,7 +208,7 @@ public StateReport getReport(String domain) { @Override public ReportManager getReportManager() { - return m_reportManager; + return stateReportManager; } @Override @@ -221,6 +218,32 @@ public boolean isEligable(MessageTree tree) { return heartbeats.size() > 0; } + public void setMIp(String ip) { + this.ip = ip; + } + + public void setProjectService(ProjectService projectService) { + this.projectService = projectService; + } + + public void setReportManager(ReportManager reportManager) { + stateReportManager = reportManager; + } + + public void setServerFilterConfigManager(ServerFilterConfigManager serverFilterConfigManager) { + this.serverFilterConfigManager = serverFilterConfigManager; + } + + public void setServerStateManager(ServerStatisticManager serverStateManager) { + serverStatisticManager = serverStateManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + @Override protected void loadReports() { // do nothing @@ -230,17 +253,17 @@ protected void loadReports() { protected void process(MessageTree tree) { String domain = tree.getDomain(); - if (m_serverFilterConfigManager.validateDomain(domain)) { - StateReport report = m_reportManager.getHourlyReport(getStartTime(), Constants.CAT, true); + if (serverFilterConfigManager.validateDomain(domain)) { + StateReport report = stateReportManager.getHourlyReport(getStartTime(), Constants.CAT, true); String ip = tree.getIpAddress(); Machine machine = report.findOrCreateMachine(NetworkInterfaceManager.INSTANCE.getLocalHostAddress()); machine.findOrCreateProcessDomain(domain).addIp(ip); - Project project = m_projectService.findProject(domain); + Project project = projectService.findProject(domain); if (project == null) { - m_projectService.insert(domain); + projectService.insert(domain); } } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateDelegate.java index dfa729463c..2ed8675d13 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/StateDelegate.java @@ -27,20 +27,15 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Calendar; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = StateAnalyzer.ID) public class StateDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ReportBucketManager m_bucketManager; @Override @@ -123,4 +118,12 @@ public StateReport parseBinary(byte[] bytes) { public StateReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setBucketManager(ReportBucketManager bucketManager) { + m_bucketManager = bucketManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/BaseEntity.java new file mode 100644 index 0000000000..27e5972241 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.state.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.state.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/Constants.java new file mode 100644 index 0000000000..a46da71e96 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/Constants.java @@ -0,0 +1,72 @@ +package com.dianping.cat.consumer.state.model; + +public class Constants { + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_AVGTPS = "avgTps"; + + public static final String ATTR_BLOCKLOSS = "blockLoss"; + + public static final String ATTR_BLOCKTIME = "blockTime"; + + public static final String ATTR_BLOCKTOTAL = "blockTotal"; + + public static final String ATTR_DELAYAVG = "delayAvg"; + + public static final String ATTR_DELAYCOUNT = "delayCount"; + + public static final String ATTR_DELAYSUM = "delaySum"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_DUMP = "dump"; + + public static final String ATTR_DUMPLOSS = "dumpLoss"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_MAXTPS = "maxTps"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_NETWORKTIMEERROR = "networkTimeError"; + + public static final String ATTR_PIGEONTIMEERROR = "pigeonTimeError"; + + public static final String ATTR_SIZE = "size"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_TIME = "time"; + + public static final String ATTR_TOTAL = "total"; + + public static final String ATTR_TOTALLOSS = "totalLoss"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ENTITY_DETAIL = "detail"; + + public static final String ENTITY_DETAILS = "details"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_MESSAGE = "message"; + + public static final String ENTITY_MESSAGES = "messages"; + + public static final String ENTITY_PROCESSDOMAIN = "processDomain"; + + public static final String ENTITY_PROCESSDOMAINS = "processDomains"; + + public static final String ENTITY_STATE_REPORT = "state-report"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IEntity.java new file mode 100644 index 0000000000..eae419a0e5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.state.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IVisitor.java new file mode 100644 index 0000000000..4222225422 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/IVisitor.java @@ -0,0 +1,20 @@ +package com.dianping.cat.consumer.state.model; + +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public interface IVisitor { + + public void visitDetail(Detail detail); + + public void visitMachine(Machine machine); + + public void visitMessage(Message message); + + public void visitProcessDomain(ProcessDomain processDomain); + + public void visitStateReport(StateReport stateReport); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Detail.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Detail.java new file mode 100644 index 0000000000..dccc390d29 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Detail.java @@ -0,0 +1,101 @@ +package com.dianping.cat.consumer.state.model.entity; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_DETAIL; + +import com.dianping.cat.consumer.state.model.BaseEntity; +import com.dianping.cat.consumer.state.model.IVisitor; + +public class Detail extends BaseEntity { + private Long m_id; + + private long m_total; + + private double m_size; + + private long m_totalLoss; + + public Detail() { + } + + public Detail(Long id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDetail(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Detail) { + Detail _o = (Detail) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Long getId() { + return m_id; + } + + public double getSize() { + return m_size; + } + + public long getTotal() { + return m_total; + } + + public long getTotalLoss() { + return m_totalLoss; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Detail other) { + assertAttributeEquals(other, ENTITY_DETAIL, ATTR_ID, m_id, other.getId()); + + m_total = other.getTotal(); + + m_size = other.getSize(); + + m_totalLoss = other.getTotalLoss(); + } + + public Detail setId(Long id) { + m_id = id; + return this; + } + + public Detail setSize(double size) { + m_size = size; + return this; + } + + public Detail setTotal(long total) { + m_total = total; + return this; + } + + public Detail setTotalLoss(long totalLoss) { + m_totalLoss = totalLoss; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Machine.java new file mode 100644 index 0000000000..28d0c34a3c --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Machine.java @@ -0,0 +1,332 @@ +package com.dianping.cat.consumer.state.model.entity; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MACHINE; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.state.model.BaseEntity; +import com.dianping.cat.consumer.state.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_ip; + + private Map m_processDomains = new LinkedHashMap(); + + private Map m_messages = new LinkedHashMap(); + + private long m_total; + + private long m_totalLoss; + + private double m_maxTps; + + private double m_avgTps; + + private long m_blockTotal; + + private long m_blockLoss; + + private long m_blockTime; + + private long m_pigeonTimeError; + + private long m_networkTimeError; + + private long m_dump; + + private long m_dumpLoss; + + private double m_size; + + private double m_delaySum; + + private double m_delayAvg; + + private int m_delayCount; + + public Machine() { + } + + public Machine(String ip) { + m_ip = ip; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addMessage(Message message) { + m_messages.put(message.getId(), message); + return this; + } + + public Machine addProcessDomain(ProcessDomain processDomain) { + m_processDomains.put(processDomain.getName(), processDomain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getIp(), _o.getIp())) { + return false; + } + + return true; + } + + return false; + } + + public Message findMessage(Long id) { + return m_messages.get(id); + } + + public ProcessDomain findProcessDomain(String name) { + return m_processDomains.get(name); + } + + public Message findOrCreateMessage(Long id) { + Message message = m_messages.get(id); + + if (message == null) { + synchronized (m_messages) { + message = m_messages.get(id); + + if (message == null) { + message = new Message(id); + m_messages.put(id, message); + } + } + } + + return message; + } + + public ProcessDomain findOrCreateProcessDomain(String name) { + ProcessDomain processDomain = m_processDomains.get(name); + + if (processDomain == null) { + synchronized (m_processDomains) { + processDomain = m_processDomains.get(name); + + if (processDomain == null) { + processDomain = new ProcessDomain(name); + m_processDomains.put(name, processDomain); + } + } + } + + return processDomain; + } + + public double getAvgTps() { + return m_avgTps; + } + + public long getBlockLoss() { + return m_blockLoss; + } + + public long getBlockTime() { + return m_blockTime; + } + + public long getBlockTotal() { + return m_blockTotal; + } + + public double getDelayAvg() { + return m_delayAvg; + } + + public int getDelayCount() { + return m_delayCount; + } + + public double getDelaySum() { + return m_delaySum; + } + + public long getDump() { + return m_dump; + } + + public long getDumpLoss() { + return m_dumpLoss; + } + + public String getIp() { + return m_ip; + } + + public double getMaxTps() { + return m_maxTps; + } + + public Map getMessages() { + return m_messages; + } + + public long getNetworkTimeError() { + return m_networkTimeError; + } + + public long getPigeonTimeError() { + return m_pigeonTimeError; + } + + public Map getProcessDomains() { + return m_processDomains; + } + + public double getSize() { + return m_size; + } + + public long getTotal() { + return m_total; + } + + public long getTotalLoss() { + return m_totalLoss; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_ip == null ? 0 : m_ip.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_IP, m_ip, other.getIp()); + + m_total = other.getTotal(); + + m_totalLoss = other.getTotalLoss(); + + m_maxTps = other.getMaxTps(); + + m_avgTps = other.getAvgTps(); + + m_blockTotal = other.getBlockTotal(); + + m_blockLoss = other.getBlockLoss(); + + m_blockTime = other.getBlockTime(); + + m_pigeonTimeError = other.getPigeonTimeError(); + + m_networkTimeError = other.getNetworkTimeError(); + + m_dump = other.getDump(); + + m_dumpLoss = other.getDumpLoss(); + + m_size = other.getSize(); + + m_delaySum = other.getDelaySum(); + + m_delayAvg = other.getDelayAvg(); + + m_delayCount = other.getDelayCount(); + } + + public Message removeMessage(Long id) { + return m_messages.remove(id); + } + + public ProcessDomain removeProcessDomain(String name) { + return m_processDomains.remove(name); + } + + public Machine setAvgTps(double avgTps) { + m_avgTps = avgTps; + return this; + } + + public Machine setBlockLoss(long blockLoss) { + m_blockLoss = blockLoss; + return this; + } + + public Machine setBlockTime(long blockTime) { + m_blockTime = blockTime; + return this; + } + + public Machine setBlockTotal(long blockTotal) { + m_blockTotal = blockTotal; + return this; + } + + public Machine setDelayAvg(double delayAvg) { + m_delayAvg = delayAvg; + return this; + } + + public Machine setDelayCount(int delayCount) { + m_delayCount = delayCount; + return this; + } + + public Machine setDelaySum(double delaySum) { + m_delaySum = delaySum; + return this; + } + + public Machine setDump(long dump) { + m_dump = dump; + return this; + } + + public Machine setDumpLoss(long dumpLoss) { + m_dumpLoss = dumpLoss; + return this; + } + + public Machine setIp(String ip) { + m_ip = ip; + return this; + } + + public Machine setMaxTps(double maxTps) { + m_maxTps = maxTps; + return this; + } + + public Machine setNetworkTimeError(long networkTimeError) { + m_networkTimeError = networkTimeError; + return this; + } + + public Machine setPigeonTimeError(long pigeonTimeError) { + m_pigeonTimeError = pigeonTimeError; + return this; + } + + public Machine setSize(double size) { + m_size = size; + return this; + } + + public Machine setTotal(long total) { + m_total = total; + return this; + } + + public Machine setTotalLoss(long totalLoss) { + m_totalLoss = totalLoss; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Message.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Message.java new file mode 100644 index 0000000000..2cabe13958 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/Message.java @@ -0,0 +1,233 @@ +package com.dianping.cat.consumer.state.model.entity; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MESSAGE; + +import com.dianping.cat.consumer.state.model.BaseEntity; +import com.dianping.cat.consumer.state.model.IVisitor; + +public class Message extends BaseEntity { + private Long m_id; + + private java.util.Date m_time; + + private long m_total; + + private long m_totalLoss; + + private long m_dump; + + private long m_dumpLoss; + + private double m_size; + + private double m_delaySum; + + private int m_delayCount; + + private long m_pigeonTimeError; + + private long m_networkTimeError; + + private long m_blockTotal; + + private long m_blockLoss; + + private long m_blockTime; + + public Message() { + } + + public Message(Long id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMessage(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Message) { + Message _o = (Message) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public long getBlockLoss() { + return m_blockLoss; + } + + public long getBlockTime() { + return m_blockTime; + } + + public long getBlockTotal() { + return m_blockTotal; + } + + public int getDelayCount() { + return m_delayCount; + } + + public double getDelaySum() { + return m_delaySum; + } + + public long getDump() { + return m_dump; + } + + public long getDumpLoss() { + return m_dumpLoss; + } + + public Long getId() { + return m_id; + } + + public long getNetworkTimeError() { + return m_networkTimeError; + } + + public long getPigeonTimeError() { + return m_pigeonTimeError; + } + + public double getSize() { + return m_size; + } + + public java.util.Date getTime() { + return m_time; + } + + public long getTotal() { + return m_total; + } + + public long getTotalLoss() { + return m_totalLoss; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Message other) { + assertAttributeEquals(other, ENTITY_MESSAGE, ATTR_ID, m_id, other.getId()); + + if (other.getTime() != null) { + m_time = other.getTime(); + } + + m_total = other.getTotal(); + + m_totalLoss = other.getTotalLoss(); + + m_dump = other.getDump(); + + m_dumpLoss = other.getDumpLoss(); + + m_size = other.getSize(); + + m_delaySum = other.getDelaySum(); + + m_delayCount = other.getDelayCount(); + + m_pigeonTimeError = other.getPigeonTimeError(); + + m_networkTimeError = other.getNetworkTimeError(); + + m_blockTotal = other.getBlockTotal(); + + m_blockLoss = other.getBlockLoss(); + + m_blockTime = other.getBlockTime(); + } + + public Message setBlockLoss(long blockLoss) { + m_blockLoss = blockLoss; + return this; + } + + public Message setBlockTime(long blockTime) { + m_blockTime = blockTime; + return this; + } + + public Message setBlockTotal(long blockTotal) { + m_blockTotal = blockTotal; + return this; + } + + public Message setDelayCount(int delayCount) { + m_delayCount = delayCount; + return this; + } + + public Message setDelaySum(double delaySum) { + m_delaySum = delaySum; + return this; + } + + public Message setDump(long dump) { + m_dump = dump; + return this; + } + + public Message setDumpLoss(long dumpLoss) { + m_dumpLoss = dumpLoss; + return this; + } + + public Message setId(Long id) { + m_id = id; + return this; + } + + public Message setNetworkTimeError(long networkTimeError) { + m_networkTimeError = networkTimeError; + return this; + } + + public Message setPigeonTimeError(long pigeonTimeError) { + m_pigeonTimeError = pigeonTimeError; + return this; + } + + public Message setSize(double size) { + m_size = size; + return this; + } + + public Message setTime(java.util.Date time) { + m_time = time; + return this; + } + + public Message setTotal(long total) { + m_total = total; + return this; + } + + public Message setTotalLoss(long totalLoss) { + m_totalLoss = totalLoss; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/ProcessDomain.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/ProcessDomain.java new file mode 100644 index 0000000000..75481c2612 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/ProcessDomain.java @@ -0,0 +1,166 @@ +package com.dianping.cat.consumer.state.model.entity; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_PROCESSDOMAIN; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.state.model.BaseEntity; +import com.dianping.cat.consumer.state.model.IVisitor; + +public class ProcessDomain extends BaseEntity { + private String m_name; + + private Set m_ips = new LinkedHashSet(); + + private long m_total; + + private long m_totalLoss; + + private double m_size; + + private double m_avg; + + private Map m_details = new LinkedHashMap(); + + public ProcessDomain() { + } + + public ProcessDomain(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitProcessDomain(this); + } + + public ProcessDomain addDetail(Detail detail) { + m_details.put(detail.getId(), detail); + return this; + } + + public ProcessDomain addIp(String ip) { + m_ips.add(ip); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ProcessDomain) { + ProcessDomain _o = (ProcessDomain) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public Detail findDetail(Long id) { + return m_details.get(id); + } + + public Detail findOrCreateDetail(Long id) { + Detail detail = m_details.get(id); + + if (detail == null) { + synchronized (m_details) { + detail = m_details.get(id); + + if (detail == null) { + detail = new Detail(id); + m_details.put(id, detail); + } + } + } + + return detail; + } + + public double getAvg() { + return m_avg; + } + + public Map getDetails() { + return m_details; + } + + public Set getIps() { + return m_ips; + } + + public String getName() { + return m_name; + } + + public double getSize() { + return m_size; + } + + public long getTotal() { + return m_total; + } + + public long getTotalLoss() { + return m_totalLoss; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ProcessDomain other) { + assertAttributeEquals(other, ENTITY_PROCESSDOMAIN, ATTR_NAME, m_name, other.getName()); + + m_total = other.getTotal(); + + m_totalLoss = other.getTotalLoss(); + + m_size = other.getSize(); + + m_avg = other.getAvg(); + } + + public Detail removeDetail(Long id) { + return m_details.remove(id); + } + + public ProcessDomain setAvg(double avg) { + m_avg = avg; + return this; + } + + public ProcessDomain setName(String name) { + m_name = name; + return this; + } + + public ProcessDomain setSize(double size) { + m_size = size; + return this; + } + + public ProcessDomain setTotal(long total) { + m_total = total; + return this; + } + + public ProcessDomain setTotalLoss(long totalLoss) { + m_totalLoss = totalLoss; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/StateReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/StateReport.java new file mode 100644 index 0000000000..f0f442a864 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/entity/StateReport.java @@ -0,0 +1,131 @@ +package com.dianping.cat.consumer.state.model.entity; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_STATE_REPORT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.state.model.BaseEntity; +import com.dianping.cat.consumer.state.model.IVisitor; + +public class StateReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_machines = new LinkedHashMap(); + + public StateReport() { + } + + public StateReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitStateReport(this); + } + + public StateReport addMachine(Machine machine) { + m_machines.put(machine.getIp(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StateReport) { + StateReport _o = (StateReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String ip) { + return m_machines.get(ip); + } + + public Machine findOrCreateMachine(String ip) { + Machine machine = m_machines.get(ip); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(ip); + + if (machine == null) { + machine = new Machine(ip); + m_machines.put(ip, machine); + } + } + } + + return machine; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Map getMachines() { + return m_machines; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(StateReport other) { + assertAttributeEquals(other, ENTITY_STATE_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String ip) { + return m_machines.remove(ip); + } + + public StateReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public StateReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public StateReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..0f0810f004 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/BaseVisitor.java @@ -0,0 +1,43 @@ +package com.dianping.cat.consumer.state.model.transform; + +import com.dianping.cat.consumer.state.model.IVisitor; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDetail(Detail detail) { + } + + @Override + public void visitMachine(Machine machine) { + for (ProcessDomain processDomain : machine.getProcessDomains().values()) { + visitProcessDomain(processDomain); + } + + for (Message message : machine.getMessages().values()) { + visitMessage(message); + } + } + + @Override + public void visitMessage(Message message) { + } + + @Override + public void visitProcessDomain(ProcessDomain processDomain) { + for (Detail detail : processDomain.getDetails().values()) { + visitDetail(detail); + } + } + + @Override + public void visitStateReport(StateReport stateReport) { + for (Machine machine : stateReport.getMachines().values()) { + visitMachine(machine); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..b3602a7aa1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultLinker.java @@ -0,0 +1,89 @@ +package com.dianping.cat.consumer.state.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDetail(final ProcessDomain parent, final Detail detail) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDetail(detail); + } + }); + } else { + parent.addDetail(detail); + } + + return true; + } + + @Override + public boolean onMachine(final StateReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onMessage(final Machine parent, final Message message) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMessage(message); + } + }); + } else { + parent.addMessage(message); + } + + return true; + } + + @Override + public boolean onProcessDomain(final Machine parent, final ProcessDomain processDomain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addProcessDomain(processDomain); + } + }); + } else { + parent.addProcessDomain(processDomain); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..d07f792c2e --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultMerger.java @@ -0,0 +1,165 @@ +package com.dianping.cat.consumer.state.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.state.model.IEntity; +import com.dianping.cat.consumer.state.model.IVisitor; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private StateReport m_stateReport; + + public DefaultMerger() { + } + + public DefaultMerger(StateReport stateReport) { + m_stateReport = stateReport; + m_objs.push(stateReport); + } + + public StateReport getStateReport() { + return m_stateReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDetail(Detail to, Detail from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeMessage(Message to, Message from) { + to.mergeAttributes(from); + } + + protected void mergeProcessDomain(ProcessDomain to, ProcessDomain from) { + to.mergeAttributes(from); + to.getIps().addAll(from.getIps()); + } + + protected void mergeStateReport(StateReport to, StateReport from) { + to.mergeAttributes(from); + } + + @Override + public void visitDetail(Detail from) { + Detail to = (Detail) m_objs.peek(); + + mergeDetail(to, from); + visitDetailChildren(to, from); + } + + protected void visitDetailChildren(Detail to, Detail from) { + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (ProcessDomain source : from.getProcessDomains().values()) { + ProcessDomain target = to.findProcessDomain(source.getName()); + + if (target == null) { + target = new ProcessDomain(source.getName()); + to.addProcessDomain(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Message source : from.getMessages().values()) { + Message target = to.findMessage(source.getId()); + + if (target == null) { + target = new Message(source.getId()); + to.addMessage(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitMessage(Message from) { + Message to = (Message) m_objs.peek(); + + mergeMessage(to, from); + visitMessageChildren(to, from); + } + + protected void visitMessageChildren(Message to, Message from) { + } + + @Override + public void visitProcessDomain(ProcessDomain from) { + ProcessDomain to = (ProcessDomain) m_objs.peek(); + + mergeProcessDomain(to, from); + visitProcessDomainChildren(to, from); + } + + protected void visitProcessDomainChildren(ProcessDomain to, ProcessDomain from) { + for (Detail source : from.getDetails().values()) { + Detail target = to.findDetail(source.getId()); + + if (target == null) { + target = new Detail(source.getId()); + to.addDetail(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitStateReport(StateReport from) { + StateReport to = (StateReport) m_objs.peek(); + + mergeStateReport(to, from); + visitStateReportChildren(to, from); + } + + protected void visitStateReportChildren(StateReport to, StateReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getIp()); + + if (target == null) { + target = new Machine(source.getIp()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..f2403e6799 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,314 @@ +package com.dianping.cat.consumer.state.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.state.model.IVisitor; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(StateReport stateReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(stateReport, out); + return out.toByteArray(); + } + + public static void build(StateReport stateReport, OutputStream out) { + stateReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDetail(Detail detail) { + if (detail.getId() != null) { + writeTag(1, 1); + writeLong(detail.getId()); + } + + writeTag(2, 0); + writeLong(detail.getTotal()); + + writeTag(3, 0); + writeDouble(detail.getSize()); + + writeTag(4, 0); + writeLong(detail.getTotalLoss()); + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getIp() != null) { + writeTag(1, 1); + writeString(machine.getIp()); + } + + writeTag(2, 0); + writeLong(machine.getTotal()); + + writeTag(3, 0); + writeLong(machine.getTotalLoss()); + + writeTag(4, 0); + writeDouble(machine.getMaxTps()); + + writeTag(5, 0); + writeDouble(machine.getAvgTps()); + + writeTag(6, 0); + writeLong(machine.getBlockTotal()); + + writeTag(7, 0); + writeLong(machine.getBlockLoss()); + + writeTag(8, 0); + writeLong(machine.getBlockTime()); + + writeTag(9, 0); + writeLong(machine.getPigeonTimeError()); + + writeTag(10, 0); + writeLong(machine.getNetworkTimeError()); + + writeTag(11, 0); + writeLong(machine.getDump()); + + writeTag(12, 0); + writeLong(machine.getDumpLoss()); + + writeTag(13, 0); + writeDouble(machine.getSize()); + + writeTag(14, 0); + writeDouble(machine.getDelaySum()); + + writeTag(15, 0); + writeDouble(machine.getDelayAvg()); + + writeTag(16, 0); + writeInt(machine.getDelayCount()); + + if (!machine.getProcessDomains().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getProcessDomains().size()); + + for (ProcessDomain processDomain : machine.getProcessDomains().values()) { + processDomain.accept(m_visitor); + } + } + + if (!machine.getMessages().isEmpty()) { + writeTag(34, 2); + writeInt(machine.getMessages().size()); + + for (Message message : machine.getMessages().values()) { + message.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitMessage(Message message) { + if (message.getId() != null) { + writeTag(1, 1); + writeLong(message.getId()); + } + + if (message.getTime() != null) { + writeTag(2, 1); + writeDate(message.getTime()); + } + + writeTag(3, 0); + writeLong(message.getTotal()); + + writeTag(4, 0); + writeLong(message.getTotalLoss()); + + writeTag(5, 0); + writeLong(message.getDump()); + + writeTag(6, 0); + writeLong(message.getDumpLoss()); + + writeTag(7, 0); + writeDouble(message.getSize()); + + writeTag(8, 0); + writeDouble(message.getDelaySum()); + + writeTag(9, 0); + writeInt(message.getDelayCount()); + + writeTag(10, 0); + writeLong(message.getPigeonTimeError()); + + writeTag(11, 0); + writeLong(message.getNetworkTimeError()); + + writeTag(12, 0); + writeLong(message.getBlockTotal()); + + writeTag(13, 0); + writeLong(message.getBlockLoss()); + + writeTag(14, 0); + writeLong(message.getBlockTime()); + + writeTag(63, 3); + } + + @Override + public void visitProcessDomain(ProcessDomain processDomain) { + if (processDomain.getName() != null) { + writeTag(1, 1); + writeString(processDomain.getName()); + } + + if (processDomain.getIps() != null) { + writeTag(2, 2); + writeInt(processDomain.getIps().size()); + + for (String ip : processDomain.getIps()) { + writeString(ip); + } + } + + writeTag(3, 0); + writeLong(processDomain.getTotal()); + + writeTag(4, 0); + writeLong(processDomain.getTotalLoss()); + + writeTag(5, 0); + writeDouble(processDomain.getSize()); + + writeTag(6, 0); + writeDouble(processDomain.getAvg()); + + if (!processDomain.getDetails().isEmpty()) { + writeTag(33, 2); + writeInt(processDomain.getDetails().size()); + + for (Detail detail : processDomain.getDetails().values()) { + detail.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitStateReport(StateReport stateReport) { + writeTag(63, 0); + + if (stateReport.getDomain() != null) { + writeTag(1, 1); + writeString(stateReport.getDomain()); + } + + if (stateReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(stateReport.getStartTime()); + } + + if (stateReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(stateReport.getEndTime()); + } + + if (!stateReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(stateReport.getMachines().size()); + + for (Machine machine : stateReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..18a2824e70 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultNativeParser.java @@ -0,0 +1,379 @@ +package com.dianping.cat.consumer.state.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.state.model.IVisitor; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static StateReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static StateReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + StateReport stateReport = new StateReport(); + + try { + stateReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return stateReport; + } + + @Override + public void visitDetail(Detail detail) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDetailChildren(detail, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDetailChildren(Detail detail, int _field, int _type) { + switch (_field) { + case 1: + detail.setId(readLong()); + break; + case 2: + detail.setTotal(readLong()); + break; + case 3: + detail.setSize(readDouble()); + break; + case 4: + detail.setTotalLoss(readLong()); + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setIp(readString()); + break; + case 2: + machine.setTotal(readLong()); + break; + case 3: + machine.setTotalLoss(readLong()); + break; + case 4: + machine.setMaxTps(readDouble()); + break; + case 5: + machine.setAvgTps(readDouble()); + break; + case 6: + machine.setBlockTotal(readLong()); + break; + case 7: + machine.setBlockLoss(readLong()); + break; + case 8: + machine.setBlockTime(readLong()); + break; + case 9: + machine.setPigeonTimeError(readLong()); + break; + case 10: + machine.setNetworkTimeError(readLong()); + break; + case 11: + machine.setDump(readLong()); + break; + case 12: + machine.setDumpLoss(readLong()); + break; + case 13: + machine.setSize(readDouble()); + break; + case 14: + machine.setDelaySum(readDouble()); + break; + case 15: + machine.setDelayAvg(readDouble()); + break; + case 16: + machine.setDelayCount(readInt()); + break; + case 33: + if (_type == 1) { + ProcessDomain processDomain = new ProcessDomain(); + + visitProcessDomain(processDomain); + m_linker.onProcessDomain(machine, processDomain); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + ProcessDomain processDomain = new ProcessDomain(); + + visitProcessDomain(processDomain); + m_linker.onProcessDomain(machine, processDomain); + } + } + break; + case 34: + if (_type == 1) { + Message message = new Message(); + + visitMessage(message); + m_linker.onMessage(machine, message); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Message message = new Message(); + + visitMessage(message); + m_linker.onMessage(machine, message); + } + } + break; + } + } + + @Override + public void visitMessage(Message message) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMessageChildren(message, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMessageChildren(Message message, int _field, int _type) { + switch (_field) { + case 1: + message.setId(readLong()); + break; + case 2: + message.setTime(readDate()); + break; + case 3: + message.setTotal(readLong()); + break; + case 4: + message.setTotalLoss(readLong()); + break; + case 5: + message.setDump(readLong()); + break; + case 6: + message.setDumpLoss(readLong()); + break; + case 7: + message.setSize(readDouble()); + break; + case 8: + message.setDelaySum(readDouble()); + break; + case 9: + message.setDelayCount(readInt()); + break; + case 10: + message.setPigeonTimeError(readLong()); + break; + case 11: + message.setNetworkTimeError(readLong()); + break; + case 12: + message.setBlockTotal(readLong()); + break; + case 13: + message.setBlockLoss(readLong()); + break; + case 14: + message.setBlockTime(readLong()); + break; + } + } + + @Override + public void visitProcessDomain(ProcessDomain processDomain) { + byte tag; + + while ((tag = readTag()) != -1) { + visitProcessDomainChildren(processDomain, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitProcessDomainChildren(ProcessDomain processDomain, int _field, int _type) { + switch (_field) { + case 1: + processDomain.setName(readString()); + break; + case 2: + if (_type == 1) { + processDomain.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + processDomain.addIp(readString()); + } + } + break; + case 3: + processDomain.setTotal(readLong()); + break; + case 4: + processDomain.setTotalLoss(readLong()); + break; + case 5: + processDomain.setSize(readDouble()); + break; + case 6: + processDomain.setAvg(readDouble()); + break; + case 33: + if (_type == 1) { + Detail detail = new Detail(); + + visitDetail(detail); + m_linker.onDetail(processDomain, detail); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Detail detail = new Detail(); + + visitDetail(detail); + m_linker.onDetail(processDomain, detail); + } + } + break; + } + } + + @Override + public void visitStateReport(StateReport stateReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitStateReportChildren(stateReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitStateReportChildren(StateReport stateReport, int _field, int _type) { + switch (_field) { + case 1: + stateReport.setDomain(readString()); + break; + case 2: + stateReport.setStartTime(readDate()); + break; + case 3: + stateReport.setEndTime(readDate()); + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(stateReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(stateReport, machine); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..70012ed890 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxMaker.java @@ -0,0 +1,317 @@ +package com.dianping.cat.consumer.state.model.transform; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_AVGTPS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKLOSS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKTOTAL; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYAVG; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYCOUNT; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYSUM; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DUMP; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DUMPLOSS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_MAXTPS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_NETWORKTIMEERROR; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_PIGEONTIMEERROR; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_SIZE; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TOTAL; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TOTALLOSS; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Detail buildDetail(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String total = attributes.getValue(ATTR_TOTAL); + String size = attributes.getValue(ATTR_SIZE); + String totalLoss = attributes.getValue(ATTR_TOTALLOSS); + Detail detail = new Detail(id == null ? null : convert(Long.class, id, null)); + + if (total != null) { + detail.setTotal(convert(Long.class, total, 0L)); + } + + if (size != null) { + detail.setSize(toNumber(size, "0.0", 0).doubleValue()); + } + + if (totalLoss != null) { + detail.setTotalLoss(convert(Long.class, totalLoss, 0L)); + } + + return detail; + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String ip = attributes.getValue(ATTR_IP); + String total = attributes.getValue(ATTR_TOTAL); + String totalLoss = attributes.getValue(ATTR_TOTALLOSS); + String maxTps = attributes.getValue(ATTR_MAXTPS); + String avgTps = attributes.getValue(ATTR_AVGTPS); + String blockTotal = attributes.getValue(ATTR_BLOCKTOTAL); + String blockLoss = attributes.getValue(ATTR_BLOCKLOSS); + String blockTime = attributes.getValue(ATTR_BLOCKTIME); + String pigeonTimeError = attributes.getValue(ATTR_PIGEONTIMEERROR); + String networkTimeError = attributes.getValue(ATTR_NETWORKTIMEERROR); + String dump = attributes.getValue(ATTR_DUMP); + String dumpLoss = attributes.getValue(ATTR_DUMPLOSS); + String size = attributes.getValue(ATTR_SIZE); + String delaySum = attributes.getValue(ATTR_DELAYSUM); + String delayAvg = attributes.getValue(ATTR_DELAYAVG); + String delayCount = attributes.getValue(ATTR_DELAYCOUNT); + Machine machine = new Machine(ip); + + if (total != null) { + machine.setTotal(convert(Long.class, total, 0L)); + } + + if (totalLoss != null) { + machine.setTotalLoss(convert(Long.class, totalLoss, 0L)); + } + + if (maxTps != null) { + machine.setMaxTps(toNumber(maxTps, "0.0", 0).doubleValue()); + } + + if (avgTps != null) { + machine.setAvgTps(toNumber(avgTps, "0.0", 0).doubleValue()); + } + + if (blockTotal != null) { + machine.setBlockTotal(convert(Long.class, blockTotal, 0L)); + } + + if (blockLoss != null) { + machine.setBlockLoss(convert(Long.class, blockLoss, 0L)); + } + + if (blockTime != null) { + machine.setBlockTime(convert(Long.class, blockTime, 0L)); + } + + if (pigeonTimeError != null) { + machine.setPigeonTimeError(convert(Long.class, pigeonTimeError, 0L)); + } + + if (networkTimeError != null) { + machine.setNetworkTimeError(convert(Long.class, networkTimeError, 0L)); + } + + if (dump != null) { + machine.setDump(convert(Long.class, dump, 0L)); + } + + if (dumpLoss != null) { + machine.setDumpLoss(convert(Long.class, dumpLoss, 0L)); + } + + if (size != null) { + machine.setSize(toNumber(size, "0.0", 0).doubleValue()); + } + + if (delaySum != null) { + machine.setDelaySum(toNumber(delaySum, "0.0", 0).doubleValue()); + } + + if (delayAvg != null) { + machine.setDelayAvg(toNumber(delayAvg, "0.0", 0).doubleValue()); + } + + if (delayCount != null) { + machine.setDelayCount(convert(Integer.class, delayCount, 0)); + } + + return machine; + } + + @Override + public Message buildMessage(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String time = attributes.getValue(ATTR_TIME); + String total = attributes.getValue(ATTR_TOTAL); + String totalLoss = attributes.getValue(ATTR_TOTALLOSS); + String dump = attributes.getValue(ATTR_DUMP); + String dumpLoss = attributes.getValue(ATTR_DUMPLOSS); + String size = attributes.getValue(ATTR_SIZE); + String delaySum = attributes.getValue(ATTR_DELAYSUM); + String delayCount = attributes.getValue(ATTR_DELAYCOUNT); + String pigeonTimeError = attributes.getValue(ATTR_PIGEONTIMEERROR); + String networkTimeError = attributes.getValue(ATTR_NETWORKTIMEERROR); + String blockTotal = attributes.getValue(ATTR_BLOCKTOTAL); + String blockLoss = attributes.getValue(ATTR_BLOCKLOSS); + String blockTime = attributes.getValue(ATTR_BLOCKTIME); + Message message = new Message(id == null ? null : convert(Long.class, id, null)); + + if (time != null) { + message.setTime(toDate(time, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (total != null) { + message.setTotal(convert(Long.class, total, 0L)); + } + + if (totalLoss != null) { + message.setTotalLoss(convert(Long.class, totalLoss, 0L)); + } + + if (dump != null) { + message.setDump(convert(Long.class, dump, 0L)); + } + + if (dumpLoss != null) { + message.setDumpLoss(convert(Long.class, dumpLoss, 0L)); + } + + if (size != null) { + message.setSize(toNumber(size, "0.0", 0).doubleValue()); + } + + if (delaySum != null) { + message.setDelaySum(toNumber(delaySum, "0.0", 0).doubleValue()); + } + + if (delayCount != null) { + message.setDelayCount(convert(Integer.class, delayCount, 0)); + } + + if (pigeonTimeError != null) { + message.setPigeonTimeError(convert(Long.class, pigeonTimeError, 0L)); + } + + if (networkTimeError != null) { + message.setNetworkTimeError(convert(Long.class, networkTimeError, 0L)); + } + + if (blockTotal != null) { + message.setBlockTotal(convert(Long.class, blockTotal, 0L)); + } + + if (blockLoss != null) { + message.setBlockLoss(convert(Long.class, blockLoss, 0L)); + } + + if (blockTime != null) { + message.setBlockTime(convert(Long.class, blockTime, 0L)); + } + + return message; + } + + @Override + public ProcessDomain buildProcessDomain(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + String total = attributes.getValue(ATTR_TOTAL); + String totalLoss = attributes.getValue(ATTR_TOTALLOSS); + String size = attributes.getValue(ATTR_SIZE); + String avg = attributes.getValue(ATTR_AVG); + ProcessDomain processDomain = new ProcessDomain(name); + + if (total != null) { + processDomain.setTotal(convert(Long.class, total, 0L)); + } + + if (totalLoss != null) { + processDomain.setTotalLoss(convert(Long.class, totalLoss, 0L)); + } + + if (size != null) { + processDomain.setSize(toNumber(size, "0.0", 0).doubleValue()); + } + + if (avg != null) { + processDomain.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + return processDomain; + } + + @Override + public StateReport buildStateReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + StateReport stateReport = new StateReport(domain); + + if (startTime != null) { + stateReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + stateReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return stateReport; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..894e08efe4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultSaxParser.java @@ -0,0 +1,324 @@ +package com.dianping.cat.consumer.state.model.transform; + +import static com.dianping.cat.consumer.state.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.state.model.Constants.ELEMENT_IPS; + +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_DETAIL; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MESSAGE; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_PROCESSDOMAIN; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_STATE_REPORT; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_PROCESSDOMAINS; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.state.model.IEntity; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static StateReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(StateReport.class, new InputSource(removeBOM(in))); + } + + public static StateReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(StateReport.class, new InputSource(removeBOM(reader))); + } + + public static StateReport parse(String xml) throws SAXException, IOException { + return parseEntity(StateReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof ProcessDomain) { + ProcessDomain processDomain = (ProcessDomain) currentObj; + + if (ELEMENT_IP.equals(currentTag)) { + processDomain.addIp(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDetail(Detail parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PROCESSDOMAINS.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_PROCESSDOMAIN.equals(qName)) { + ProcessDomain processDomain = m_maker.buildProcessDomain(attributes); + + m_linker.onProcessDomain(parentObj, processDomain); + m_objs.push(processDomain); + } else if (ENTITY_MESSAGE.equals(qName)) { + Message message = m_maker.buildMessage(attributes); + + m_linker.onMessage(parentObj, message); + m_objs.push(message); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForMessage(Message parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForProcessDomain(ProcessDomain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_DETAIL.equals(qName)) { + Detail detail = m_maker.buildDetail(attributes); + + m_linker.onDetail(parentObj, detail); + m_objs.push(detail); + } else { + throw new SAXException(String.format("Element(%s) is not expected under processDomain!", qName)); + } + + m_tags.push(qName); + } + + private void parseForStateReport(StateReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under state-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_STATE_REPORT.equals(qName)) { + StateReport stateReport = m_maker.buildStateReport(attributes); + + m_entity = stateReport; + m_objs.push(stateReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_PROCESSDOMAIN.equals(qName)) { + ProcessDomain processDomain = m_maker.buildProcessDomain(attributes); + + m_entity = processDomain; + m_objs.push(processDomain); + m_tags.push(qName); + } else if (ENTITY_MESSAGE.equals(qName)) { + Message message = m_maker.buildMessage(attributes); + + m_entity = message; + m_objs.push(message); + m_tags.push(qName); + } else if (ENTITY_DETAIL.equals(qName)) { + Detail detail = m_maker.buildDetail(attributes); + + m_entity = detail; + m_objs.push(detail); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof StateReport) { + parseForStateReport((StateReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof ProcessDomain) { + parseForProcessDomain((ProcessDomain) parent, tag, qName, attributes); + } else if (parent instanceof Message) { + parseForMessage((Message) parent, tag, qName, attributes); + } else if (parent instanceof Detail) { + parseForDetail((Detail) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..30ad981e4f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,348 @@ +package com.dianping.cat.consumer.state.model.transform; + +import static com.dianping.cat.consumer.state.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_AVGTPS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKLOSS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_BLOCKTOTAL; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYAVG; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYCOUNT; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DELAYSUM; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DUMP; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_DUMPLOSS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_MAXTPS; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_NETWORKTIMEERROR; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_PIGEONTIMEERROR; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_SIZE; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TIME; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TOTAL; +import static com.dianping.cat.consumer.state.model.Constants.ATTR_TOTALLOSS; +import static com.dianping.cat.consumer.state.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_DETAIL; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_MESSAGE; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_PROCESSDOMAIN; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_PROCESSDOMAINS; +import static com.dianping.cat.consumer.state.model.Constants.ENTITY_STATE_REPORT; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.state.model.IEntity; +import com.dianping.cat.consumer.state.model.IVisitor; +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitDetail(Detail detail) { + startTag(ENTITY_DETAIL, true, null, ATTR_ID, detail.getId(), ATTR_TOTAL, detail.getTotal(), ATTR_SIZE, toString(detail.getSize(), "0.0"), ATTR_TOTALLOSS, detail.getTotalLoss()); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_IP, machine.getIp(), ATTR_TOTAL, machine.getTotal(), ATTR_TOTALLOSS, machine.getTotalLoss(), ATTR_MAXTPS, toString(machine.getMaxTps(), "0.0"), ATTR_AVGTPS, toString(machine.getAvgTps(), "0.0"), ATTR_BLOCKTOTAL, machine.getBlockTotal(), ATTR_BLOCKLOSS, machine.getBlockLoss(), ATTR_BLOCKTIME, machine.getBlockTime(), ATTR_PIGEONTIMEERROR, machine.getPigeonTimeError(), ATTR_NETWORKTIMEERROR, machine.getNetworkTimeError(), ATTR_DUMP, machine.getDump(), ATTR_DUMPLOSS, machine.getDumpLoss(), ATTR_SIZE, toString(machine.getSize(), "0.0"), ATTR_DELAYSUM, toString(machine.getDelaySum(), "0.0"), ATTR_DELAYAVG, toString(machine.getDelayAvg(), "0.0"), ATTR_DELAYCOUNT, machine.getDelayCount()); + + if (!machine.getProcessDomains().isEmpty()) { + startTag(ENTITY_PROCESSDOMAINS); + + for (ProcessDomain processDomain : machine.getProcessDomains().values()) { + processDomain.accept(m_visitor); + } + + endTag(ENTITY_PROCESSDOMAINS); + } + + if (!machine.getMessages().isEmpty()) { + for (Message message : machine.getMessages().values()) { + message.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitMessage(Message message) { + startTag(ENTITY_MESSAGE, true, null, ATTR_ID, message.getId(), ATTR_TIME, toString(message.getTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_TOTAL, message.getTotal(), ATTR_TOTALLOSS, message.getTotalLoss(), ATTR_DUMP, message.getDump(), ATTR_DUMPLOSS, message.getDumpLoss(), ATTR_SIZE, toString(message.getSize(), "0.0"), ATTR_DELAYSUM, toString(message.getDelaySum(), "0.0"), ATTR_DELAYCOUNT, message.getDelayCount(), ATTR_PIGEONTIMEERROR, message.getPigeonTimeError(), ATTR_NETWORKTIMEERROR, message.getNetworkTimeError(), ATTR_BLOCKTOTAL, message.getBlockTotal(), ATTR_BLOCKLOSS, message.getBlockLoss(), ATTR_BLOCKTIME, message.getBlockTime()); + } + + @Override + public void visitProcessDomain(ProcessDomain processDomain) { + startTag(ENTITY_PROCESSDOMAIN, null, ATTR_NAME, processDomain.getName(), ATTR_TOTAL, processDomain.getTotal(), ATTR_TOTALLOSS, processDomain.getTotalLoss(), ATTR_SIZE, toString(processDomain.getSize(), "0.0"), ATTR_AVG, toString(processDomain.getAvg(), "0.0")); + + if (!processDomain.getIps().isEmpty()) { + for (String ip : processDomain.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!processDomain.getDetails().isEmpty()) { + for (Detail detail : processDomain.getDetails().values()) { + detail.accept(m_visitor); + } + } + + endTag(ENTITY_PROCESSDOMAIN); + } + + @Override + public void visitStateReport(StateReport stateReport) { + startTag(ENTITY_STATE_REPORT, null, ATTR_DOMAIN, stateReport.getDomain(), ATTR_STARTTIME, toString(stateReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(stateReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!stateReport.getMachines().isEmpty()) { + for (Machine machine : stateReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_STATE_REPORT); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/ILinker.java new file mode 100644 index 0000000000..1d190257fc --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/ILinker.java @@ -0,0 +1,18 @@ +package com.dianping.cat.consumer.state.model.transform; + +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public interface ILinker { + + public boolean onDetail(ProcessDomain parent, Detail detail); + + public boolean onMachine(StateReport parent, Machine machine); + + public boolean onMessage(Machine parent, Message message); + + public boolean onProcessDomain(Machine parent, ProcessDomain processDomain); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IMaker.java new file mode 100644 index 0000000000..2832fce034 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IMaker.java @@ -0,0 +1,22 @@ +package com.dianping.cat.consumer.state.model.transform; + +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public interface IMaker { + + public Detail buildDetail(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public Message buildMessage(T node); + + public ProcessDomain buildProcessDomain(T node); + + public StateReport buildStateReport(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IParser.java new file mode 100644 index 0000000000..3ebd392876 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/state/model/transform/IParser.java @@ -0,0 +1,19 @@ +package com.dianping.cat.consumer.state.model.transform; + +import com.dianping.cat.consumer.state.model.entity.Detail; +import com.dianping.cat.consumer.state.model.entity.Machine; +import com.dianping.cat.consumer.state.model.entity.Message; +import com.dianping.cat.consumer.state.model.entity.ProcessDomain; +import com.dianping.cat.consumer.state.model.entity.StateReport; + +public interface IParser { + public StateReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDetail(IMaker maker, ILinker linker, Detail parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForMessage(IMaker maker, ILinker linker, Message parent, T node); + + public void parseForProcessDomain(IMaker maker, ILinker linker, ProcessDomain parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageAnalyzer.java index 73862a00f2..96aec17476 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageAnalyzer.java @@ -19,19 +19,18 @@ package com.dianping.cat.consumer.storage; import java.util.Collection; +import java.util.Collections; 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.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; -import org.unidal.lookup.util.StringUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.DatabaseParser; import com.dianping.cat.consumer.storage.StorageReportUpdater.StorageUpdateItem; import com.dianping.cat.consumer.storage.builder.StorageBuilder; @@ -41,55 +40,92 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = StorageAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class StorageAnalyzer extends AbstractMessageAnalyzer implements LogEnabled, Initializable { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + StorageAnalyzer.ID) +@Scope("prototype") +public class StorageAnalyzer extends AbstractMessageAnalyzer { + private static final Logger LOGGER = LoggerFactory.getLogger(StorageAnalyzer.class); public static final String ID = "storage"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = StorageAnalyzer.ID + "ReportManager") + private ReportManager storageReportManager; - @Inject - private DatabaseParser m_databaseParser; + @Resource(name = "databaseParser") + private DatabaseParser databaseParser; - @Inject - private StorageReportUpdater m_updater; + @Resource(name = "storageReportUpdater") + private StorageReportUpdater storageReportUpdater; - private Map m_storageBuilders; + @Resource(name = "storageBuilders") + private Map storageBuilders; + + private volatile boolean initialized; @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); - m_databaseParser.showErrorCon(); + storageReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + databaseParser.showErrorCon(); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + storageReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public StorageReport getReport(String id) { long period = getStartTime(); - StorageReport report = m_reportManager.getHourlyReport(period, id, false); + StorageReport report = storageReportManager.getHourlyReport(period, id, false); - m_updater.updateStorageIds(id, m_reportManager.getDomains(period), report); + storageReportUpdater.updateStorageIds(id, storageReportManager.getDomains(period), report); return report; } @Override public ReportManager getReportManager() { - return m_reportManager; + return storageReportManager; + } + + public void setDatabaseParser(DatabaseParser databaseParser) { + this.databaseParser = databaseParser; + } + + public void setReportManager(ReportManager reportManager) { + storageReportManager = reportManager; + } + + public void setUpdater(StorageReportUpdater updater) { + storageReportUpdater = updater; + } + + public void setStorageBuilders(Map storageBuilders) { + this.storageBuilders = storageBuilders; } @Override - public void initialize() throws InitializationException { - m_storageBuilders = lookupMap(StorageBuilder.class); + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + + private void ensureInitialized() { + if (!initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (initialized) { + return; + } + if (storageBuilders == null) { + storageBuilders = Collections.emptyMap(); + LOGGER.warn("Storage analyzer has no configured builders, keep empty builder map."); + } + initialized = true; } @Override @@ -103,16 +139,18 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + storageReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override protected void process(MessageTree tree) { + ensureInitialized(); + List transactions = tree.getTransactions(); for (Transaction t : transactions) { String domain = tree.getDomain(); - Collection builders = m_storageBuilders.values(); + Collection builders = storageBuilders.values(); for (StorageBuilder builder : builders) { if (builder.isEligable(t)) { @@ -120,12 +158,12 @@ protected void process(MessageTree tree) { String id = item.getId(); if (StringUtils.isNotEmpty(id)) { - StorageReport report = m_reportManager.getHourlyReport(getStartTime(), item.getReportId(), true); + StorageReport report = storageReportManager.getHourlyReport(getStartTime(), item.getReportId(), true); StorageUpdateItem param = new StorageUpdateItem(); param.setDomain(domain).setIp(item.getIp()).setMethod(item.getMethod()).setTransaction(t) .setThreshold(item.getThreshold()); - m_updater.updateStorageReport(report, param); + storageReportUpdater.updateStorageReport(report, param); } } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageDelegate.java index 6b70aac95e..d11198057a 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageDelegate.java @@ -26,22 +26,19 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = StorageAnalyzer.ID) public class StorageDelegate implements ReportDelegate { + private static final Logger LOGGER = LoggerFactory.getLogger(StorageDelegate.class); - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_configManager; - @Inject private StorageReportUpdater m_reportUpdater; @Override @@ -86,10 +83,17 @@ public String getDomain(StorageReport report) { public StorageReport makeReport(String id, long startTime, long duration) { StorageReport report = new StorageReport(id); int index = id.lastIndexOf("-"); - String name = id.substring(0, index); - String type = id.substring(index + 1); - report.setName(name).setType(type); + if (index <= 0 || index >= id.length() - 1) { + LOGGER.warn("Invalid storage report id, id={}, expectedFormat=-, startTime={}, duration={}.", + id, startTime, duration); + report.setName(id); + } else { + String name = id.substring(0, index); + String type = id.substring(index + 1); + + report.setName(name).setType(type); + } report.setStartTime(new Date(startTime)).setEndTime(new Date(startTime + duration - 1)); return report; @@ -113,4 +117,16 @@ public StorageReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager configManager) { + m_configManager = configManager; + } + + public void setReportUpdater(StorageReportUpdater reportUpdater) { + m_reportUpdater = reportUpdater; + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageReportUpdater.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageReportUpdater.java index dba13c5c01..e81d8d5959 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageReportUpdater.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/StorageReportUpdater.java @@ -20,15 +20,12 @@ import java.util.Set; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.consumer.storage.model.entity.Domain; import com.dianping.cat.consumer.storage.model.entity.Operation; import com.dianping.cat.consumer.storage.model.entity.Segment; import com.dianping.cat.consumer.storage.model.entity.StorageReport; import com.dianping.cat.message.Transaction; -@Named public class StorageReportUpdater { public void updateStorageIds(String id, Set ids, StorageReport report) { diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageBuilderManager.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageBuilderManager.java index 2a722b0796..f3e6873d07 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageBuilderManager.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageBuilderManager.java @@ -22,17 +22,19 @@ import java.util.List; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -@Named -public class StorageBuilderManager extends ContainerHolder implements Initializable { +public class StorageBuilderManager { + private static final Logger LOGGER = LoggerFactory.getLogger(StorageBuilderManager.class); private Map m_storageBuilders; + private volatile boolean m_initialized; + public List getDefaultMethods(String type) { + ensureInitialized(); + StorageBuilder storageBuilder = m_storageBuilders.get(type); if (storageBuilder != null) { @@ -43,12 +45,30 @@ public List getDefaultMethods(String type) { } public StorageBuilder getStorageBuilder(String type) { + ensureInitialized(); + return m_storageBuilders.get(type); } - @Override - public void initialize() throws InitializationException { - m_storageBuilders = lookupMap(StorageBuilder.class); + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + if (m_storageBuilders == null) { + m_storageBuilders = Collections.emptyMap(); + LOGGER.warn("Storage builder manager has no configured builders, keep empty builder map."); + } + m_initialized = true; + } + + public void setStorageBuilders(Map storageBuilders) { + m_storageBuilders = storageBuilders; } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageCacheBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageCacheBuilder.java index f6d1026980..03ef52a77a 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageCacheBuilder.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageCacheBuilder.java @@ -21,13 +21,10 @@ import java.util.Arrays; import java.util.List; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.message.Event; import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; -@Named(type = StorageBuilder.class, value = StorageCacheBuilder.ID) public class StorageCacheBuilder implements StorageBuilder { public final static String ID = "Cache"; diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageRPCBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageRPCBuilder.java index b07ffb7f94..4ab2642cba 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageRPCBuilder.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageRPCBuilder.java @@ -21,13 +21,10 @@ import java.util.Arrays; import java.util.List; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.message.Event; import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; -@Named(type = StorageBuilder.class, value = StorageRPCBuilder.ID) public class StorageRPCBuilder implements StorageBuilder { public final static String ID = "RPC"; diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageSQLBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageSQLBuilder.java index e261d07a1c..1042c1484b 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageSQLBuilder.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/builder/StorageSQLBuilder.java @@ -21,16 +21,12 @@ import java.util.Arrays; import java.util.List; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.consumer.DatabaseParser; import com.dianping.cat.consumer.DatabaseParser.Database; import com.dianping.cat.message.Event; import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; -@Named(type = StorageBuilder.class, value = StorageSQLBuilder.ID) public class StorageSQLBuilder implements StorageBuilder { public final static String ID = "SQL"; @@ -39,7 +35,6 @@ public class StorageSQLBuilder implements StorageBuilder { public final static List DEFAULT_METHODS = Arrays.asList("select", "delete", "insert", "update"); - @Inject private DatabaseParser m_databaseParser; @Override @@ -84,4 +79,8 @@ public boolean isEligable(Transaction t) { return "SQL".equals(t.getType()); } + public void setDatabaseParser(DatabaseParser databaseParser) { + m_databaseParser = databaseParser; + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/BaseEntity.java new file mode 100644 index 0000000000..b97fb0376b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.storage.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.storage.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/Constants.java new file mode 100644 index 0000000000..bc114d1716 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/Constants.java @@ -0,0 +1,60 @@ +package com.dianping.cat.consumer.storage.model; + +public class Constants { + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_ERROR = "error"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_LONG_COUNT = "long-count"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_STATEMENT = "statement"; + + public static final String ATTR_SUM = "sum"; + + public static final String ATTR_TYPE = "type"; + + public static final String ELEMENT_ID = "id"; + + public static final String ELEMENT_IDS = "ids"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ELEMENT_OP = "op"; + + public static final String ELEMENT_OPS = "ops"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_OPERATION = "operation"; + + public static final String ENTITY_OPERATIONS = "operations"; + + public static final String ENTITY_SEGMENT = "segment"; + + public static final String ENTITY_SEGMENTS = "segments"; + + public static final String ENTITY_SQL = "sql"; + + public static final String ENTITY_SQLS = "sqls"; + + public static final String ENTITY_STORAGE_REPORT = "storage-report"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IEntity.java new file mode 100644 index 0000000000..4c18caba04 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.storage.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IVisitor.java new file mode 100644 index 0000000000..7a6ee80844 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/IVisitor.java @@ -0,0 +1,23 @@ +package com.dianping.cat.consumer.storage.model; + +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public interface IVisitor { + + public void visitDomain(Domain domain); + + public void visitMachine(Machine machine); + + public void visitOperation(Operation operation); + + public void visitSegment(Segment segment); + + public void visitSql(Sql sql); + + public void visitStorageReport(StorageReport storageReport); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Domain.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Domain.java new file mode 100644 index 0000000000..b5af3a3bff --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Domain.java @@ -0,0 +1,138 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_DOMAIN; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class Domain extends BaseEntity { + private String m_id; + + private Map m_operations = new LinkedHashMap(); + + private Map m_sqls = new LinkedHashMap(); + + public Domain() { + } + + public Domain(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + public Domain addOperation(Operation operation) { + m_operations.put(operation.getId(), operation); + return this; + } + + public Domain addSql(Sql sql) { + m_sqls.put(sql.getId(), sql); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Operation findOperation(String id) { + return m_operations.get(id); + } + + public Sql findSql(String id) { + return m_sqls.get(id); + } + + public Operation findOrCreateOperation(String id) { + Operation operation = m_operations.get(id); + + if (operation == null) { + synchronized (m_operations) { + operation = m_operations.get(id); + + if (operation == null) { + operation = new Operation(id); + m_operations.put(id, operation); + } + } + } + + return operation; + } + + public Sql findOrCreateSql(String id) { + Sql sql = m_sqls.get(id); + + if (sql == null) { + synchronized (m_sqls) { + sql = m_sqls.get(id); + + if (sql == null) { + sql = new Sql(id); + m_sqls.put(id, sql); + } + } + } + + return sql; + } + + public String getId() { + return m_id; + } + + public Map getOperations() { + return m_operations; + } + + public Map getSqls() { + return m_sqls; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_ID, m_id, other.getId()); + + } + + public Operation removeOperation(String id) { + return m_operations.remove(id); + } + + public Sql removeSql(String id) { + return m_sqls.remove(id); + } + + public Domain setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Machine.java new file mode 100644 index 0000000000..1edee8722b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Machine.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_MACHINE; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_id; + + private Map m_domains = new LinkedHashMap(); + + public Machine() { + } + + public Machine(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addDomain(Domain domain) { + m_domains.put(domain.getId(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Domain findDomain(String id) { + return m_domains.get(id); + } + + public Domain findOrCreateDomain(String id) { + Domain domain = m_domains.get(id); + + if (domain == null) { + synchronized (m_domains) { + domain = m_domains.get(id); + + if (domain == null) { + domain = new Domain(id); + m_domains.put(id, domain); + } + } + } + + return domain; + } + + public Map getDomains() { + return m_domains; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_ID, m_id, other.getId()); + + } + + public Domain removeDomain(String id) { + return m_domains.remove(id); + } + + public Machine setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Operation.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Operation.java new file mode 100644 index 0000000000..b4e62724d9 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Operation.java @@ -0,0 +1,206 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_OPERATION; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class Operation extends BaseEntity { + private String m_id; + + private long m_count; + + private double m_avg; + + private double m_sum; + + private long m_error; + + private long m_longCount; + + private Map m_segments = new LinkedHashMap(); + + public Operation() { + } + + public Operation(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitOperation(this); + } + + public Operation addSegment(Segment segment) { + m_segments.put(segment.getId(), segment); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Operation) { + Operation _o = (Operation) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Segment findSegment(int id) { + return m_segments.get(id); + } + + public Segment findOrCreateSegment(int id) { + Segment segment = m_segments.get(id); + + if (segment == null) { + synchronized (m_segments) { + segment = m_segments.get(id); + + if (segment == null) { + segment = new Segment(id); + m_segments.put(id, segment); + } + } + } + + return segment; + } + + public double getAvg() { + return m_avg; + } + + public long getCount() { + return m_count; + } + + public long getError() { + return m_error; + } + + public String getId() { + return m_id; + } + + public long getLongCount() { + return m_longCount; + } + + public Map getSegments() { + return m_segments; + } + + public double getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Operation incCount() { + m_count++; + return this; + } + + public Operation incCount(long count) { + m_count += count; + return this; + } + + public Operation incError() { + m_error++; + return this; + } + + public Operation incError(long error) { + m_error += error; + return this; + } + + public Operation incLongCount() { + m_longCount++; + return this; + } + + public Operation incLongCount(long longCount) { + m_longCount += longCount; + return this; + } + + public Operation incSum() { + m_sum++; + return this; + } + + public Operation incSum(double sum) { + m_sum += sum; + return this; + } + + @Override + public void mergeAttributes(Operation other) { + assertAttributeEquals(other, ENTITY_OPERATION, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_error = other.getError(); + + m_longCount = other.getLongCount(); + } + + public Segment removeSegment(int id) { + return m_segments.remove(id); + } + + public Operation setAvg(double avg) { + m_avg = avg; + return this; + } + + public Operation setCount(long count) { + m_count = count; + return this; + } + + public Operation setError(long error) { + m_error = error; + return this; + } + + public Operation setId(String id) { + m_id = id; + return this; + } + + public Operation setLongCount(long longCount) { + m_longCount = longCount; + return this; + } + + public Operation setSum(double sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Segment.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Segment.java new file mode 100644 index 0000000000..c082c6575d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Segment.java @@ -0,0 +1,167 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SEGMENT; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class Segment extends BaseEntity { + private int m_id; + + private long m_count; + + private double m_avg; + + private double m_sum; + + private long m_error; + + private long m_longCount; + + public Segment() { + } + + public Segment(int id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSegment(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Segment) { + Segment _o = (Segment) obj; + + if (getId() != _o.getId()) { + return false; + } + + return true; + } + + return false; + } + + public double getAvg() { + return m_avg; + } + + public long getCount() { + return m_count; + } + + public long getError() { + return m_error; + } + + public int getId() { + return m_id; + } + + public long getLongCount() { + return m_longCount; + } + + public double getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_id; + + return hash; + } + + public Segment incCount() { + m_count++; + return this; + } + + public Segment incCount(long count) { + m_count += count; + return this; + } + + public Segment incError() { + m_error++; + return this; + } + + public Segment incError(long error) { + m_error += error; + return this; + } + + public Segment incLongCount() { + m_longCount++; + return this; + } + + public Segment incLongCount(long longCount) { + m_longCount += longCount; + return this; + } + + public Segment incSum() { + m_sum++; + return this; + } + + public Segment incSum(double sum) { + m_sum += sum; + return this; + } + + @Override + public void mergeAttributes(Segment other) { + assertAttributeEquals(other, ENTITY_SEGMENT, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_error = other.getError(); + + m_longCount = other.getLongCount(); + } + + public Segment setAvg(double avg) { + m_avg = avg; + return this; + } + + public Segment setCount(long count) { + m_count = count; + return this; + } + + public Segment setError(long error) { + m_error = error; + return this; + } + + public Segment setId(int id) { + m_id = id; + return this; + } + + public Segment setLongCount(long longCount) { + m_longCount = longCount; + return this; + } + + public Segment setSum(double sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Sql.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Sql.java new file mode 100644 index 0000000000..bae8aef584 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/Sql.java @@ -0,0 +1,100 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SQL; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class Sql extends BaseEntity { + private String m_id; + + private String m_statement; + + private int m_count; + + public Sql() { + } + + public Sql(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSql(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Sql) { + Sql _o = (Sql) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public String getId() { + return m_id; + } + + public String getStatement() { + return m_statement; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Sql incCount() { + m_count++; + return this; + } + + public Sql incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Sql other) { + assertAttributeEquals(other, ENTITY_SQL, ATTR_ID, m_id, other.getId()); + + if (other.getStatement() != null) { + m_statement = other.getStatement(); + } + + m_count = other.getCount(); + } + + public Sql setCount(int count) { + m_count = count; + return this; + } + + public Sql setId(String id) { + m_id = id; + return this; + } + + public Sql setStatement(String statement) { + m_statement = statement; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/StorageReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/StorageReport.java new file mode 100644 index 0000000000..ace8ceecec --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/entity/StorageReport.java @@ -0,0 +1,196 @@ +package com.dianping.cat.consumer.storage.model.entity; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_STORAGE_REPORT; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.consumer.storage.model.BaseEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; + +public class StorageReport extends BaseEntity { + private String m_id; + + private String m_name; + + private String m_type; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Set m_ids = new LinkedHashSet(); + + private Set m_ips = new LinkedHashSet(); + + private Set m_ops = new LinkedHashSet(); + + private Map m_machines = new LinkedHashMap(); + + public StorageReport() { + } + + public StorageReport(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitStorageReport(this); + } + + public StorageReport addId(String id) { + m_ids.add(id); + return this; + } + + public StorageReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public StorageReport addMachine(Machine machine) { + m_machines.put(machine.getId(), machine); + return this; + } + + public StorageReport addOp(String op) { + m_ops.add(op); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StorageReport) { + StorageReport _o = (StorageReport) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String id) { + return m_machines.get(id); + } + + public Machine findOrCreateMachine(String id) { + Machine machine = m_machines.get(id); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(id); + + if (machine == null) { + machine = new Machine(id); + m_machines.put(id, machine); + } + } + } + + return machine; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public String getId() { + return m_id; + } + + public Set getIds() { + return m_ids; + } + + public Set getIps() { + return m_ips; + } + + public Map getMachines() { + return m_machines; + } + + public String getName() { + return m_name; + } + + public Set getOps() { + return m_ops; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + public String getType() { + return m_type; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(StorageReport other) { + assertAttributeEquals(other, ENTITY_STORAGE_REPORT, ATTR_ID, m_id, other.getId()); + + if (other.getName() != null) { + m_name = other.getName(); + } + + if (other.getType() != null) { + m_type = other.getType(); + } + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String id) { + return m_machines.remove(id); + } + + public StorageReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public StorageReport setId(String id) { + m_id = id; + return this; + } + + public StorageReport setName(String name) { + m_name = name; + return this; + } + + public StorageReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + + public StorageReport setType(String type) { + m_type = type; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..35cb0882e4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/BaseVisitor.java @@ -0,0 +1,51 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import com.dianping.cat.consumer.storage.model.IVisitor; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDomain(Domain domain) { + for (Operation operation : domain.getOperations().values()) { + visitOperation(operation); + } + + for (Sql sql : domain.getSqls().values()) { + visitSql(sql); + } + } + + @Override + public void visitMachine(Machine machine) { + for (Domain domain : machine.getDomains().values()) { + visitDomain(domain); + } + } + + @Override + public void visitOperation(Operation operation) { + for (Segment segment : operation.getSegments().values()) { + visitSegment(segment); + } + } + + @Override + public void visitSegment(Segment segment) { + } + + @Override + public void visitSql(Sql sql) { + } + + @Override + public void visitStorageReport(StorageReport storageReport) { + for (Machine machine : storageReport.getMachines().values()) { + visitMachine(machine); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..7b7dcb5c96 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultLinker.java @@ -0,0 +1,106 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDomain(final Machine parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } + + @Override + public boolean onMachine(final StorageReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onOperation(final Domain parent, final Operation operation) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addOperation(operation); + } + }); + } else { + parent.addOperation(operation); + } + + return true; + } + + @Override + public boolean onSegment(final Operation parent, final Segment segment) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSegment(segment); + } + }); + } else { + parent.addSegment(segment); + } + + return true; + } + + @Override + public boolean onSql(final Domain parent, final Sql sql) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSql(sql); + } + }); + } else { + parent.addSql(sql); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..7b784ef8f5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultMerger.java @@ -0,0 +1,195 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.storage.model.IEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private StorageReport m_storageReport; + + public DefaultMerger() { + } + + public DefaultMerger(StorageReport storageReport) { + m_storageReport = storageReport; + m_objs.push(storageReport); + } + + public StorageReport getStorageReport() { + return m_storageReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDomain(Domain to, Domain from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeOperation(Operation to, Operation from) { + to.mergeAttributes(from); + } + + protected void mergeSegment(Segment to, Segment from) { + to.mergeAttributes(from); + } + + protected void mergeSql(Sql to, Sql from) { + to.mergeAttributes(from); + } + + protected void mergeStorageReport(StorageReport to, StorageReport from) { + to.mergeAttributes(from); + to.getIds().addAll(from.getIds()); + to.getIps().addAll(from.getIps()); + to.getOps().addAll(from.getOps()); + } + + @Override + public void visitDomain(Domain from) { + Domain to = (Domain) m_objs.peek(); + + mergeDomain(to, from); + visitDomainChildren(to, from); + } + + protected void visitDomainChildren(Domain to, Domain from) { + for (Operation source : from.getOperations().values()) { + Operation target = to.findOperation(source.getId()); + + if (target == null) { + target = new Operation(source.getId()); + to.addOperation(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Sql source : from.getSqls().values()) { + Sql target = to.findSql(source.getId()); + + if (target == null) { + target = new Sql(source.getId()); + to.addSql(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (Domain source : from.getDomains().values()) { + Domain target = to.findDomain(source.getId()); + + if (target == null) { + target = new Domain(source.getId()); + to.addDomain(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitOperation(Operation from) { + Operation to = (Operation) m_objs.peek(); + + mergeOperation(to, from); + visitOperationChildren(to, from); + } + + protected void visitOperationChildren(Operation to, Operation from) { + for (Segment source : from.getSegments().values()) { + Segment target = to.findSegment(source.getId()); + + if (target == null) { + target = new Segment(source.getId()); + to.addSegment(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitSegment(Segment from) { + Segment to = (Segment) m_objs.peek(); + + mergeSegment(to, from); + visitSegmentChildren(to, from); + } + + protected void visitSegmentChildren(Segment to, Segment from) { + } + + @Override + public void visitSql(Sql from) { + Sql to = (Sql) m_objs.peek(); + + mergeSql(to, from); + visitSqlChildren(to, from); + } + + protected void visitSqlChildren(Sql to, Sql from) { + } + + @Override + public void visitStorageReport(StorageReport from) { + StorageReport to = (StorageReport) m_objs.peek(); + + mergeStorageReport(to, from); + visitStorageReportChildren(to, from); + } + + protected void visitStorageReportChildren(StorageReport to, StorageReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getId()); + + if (target == null) { + target = new Machine(source.getId()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..40cc918796 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,291 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.storage.model.IVisitor; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(StorageReport storageReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(storageReport, out); + return out.toByteArray(); + } + + public static void build(StorageReport storageReport, OutputStream out) { + storageReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDomain(Domain domain) { + if (domain.getId() != null) { + writeTag(1, 1); + writeString(domain.getId()); + } + + if (!domain.getOperations().isEmpty()) { + writeTag(33, 2); + writeInt(domain.getOperations().size()); + + for (Operation operation : domain.getOperations().values()) { + operation.accept(m_visitor); + } + } + + if (!domain.getSqls().isEmpty()) { + writeTag(34, 2); + writeInt(domain.getSqls().size()); + + for (Sql sql : domain.getSqls().values()) { + sql.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getId() != null) { + writeTag(1, 1); + writeString(machine.getId()); + } + + if (!machine.getDomains().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getDomains().size()); + + for (Domain domain : machine.getDomains().values()) { + domain.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitOperation(Operation operation) { + if (operation.getId() != null) { + writeTag(1, 1); + writeString(operation.getId()); + } + + writeTag(2, 0); + writeLong(operation.getCount()); + + writeTag(3, 0); + writeDouble(operation.getAvg()); + + writeTag(4, 0); + writeDouble(operation.getSum()); + + writeTag(5, 0); + writeLong(operation.getError()); + + writeTag(6, 0); + writeLong(operation.getLongCount()); + + if (!operation.getSegments().isEmpty()) { + writeTag(33, 2); + writeInt(operation.getSegments().size()); + + for (Segment segment : operation.getSegments().values()) { + segment.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitSegment(Segment segment) { + writeTag(1, 0); + writeInt(segment.getId()); + + writeTag(2, 0); + writeLong(segment.getCount()); + + writeTag(3, 0); + writeDouble(segment.getAvg()); + + writeTag(4, 0); + writeDouble(segment.getSum()); + + writeTag(5, 0); + writeLong(segment.getError()); + + writeTag(6, 0); + writeLong(segment.getLongCount()); + + writeTag(63, 3); + } + + @Override + public void visitSql(Sql sql) { + if (sql.getId() != null) { + writeTag(1, 1); + writeString(sql.getId()); + } + + if (sql.getStatement() != null) { + writeTag(2, 1); + writeString(sql.getStatement()); + } + + writeTag(3, 0); + writeInt(sql.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitStorageReport(StorageReport storageReport) { + writeTag(63, 0); + + if (storageReport.getId() != null) { + writeTag(1, 1); + writeString(storageReport.getId()); + } + + if (storageReport.getName() != null) { + writeTag(2, 1); + writeString(storageReport.getName()); + } + + if (storageReport.getType() != null) { + writeTag(3, 1); + writeString(storageReport.getType()); + } + + if (storageReport.getStartTime() != null) { + writeTag(4, 1); + writeDate(storageReport.getStartTime()); + } + + if (storageReport.getEndTime() != null) { + writeTag(5, 1); + writeDate(storageReport.getEndTime()); + } + + if (storageReport.getIds() != null) { + writeTag(6, 2); + writeInt(storageReport.getIds().size()); + + for (String id : storageReport.getIds()) { + writeString(id); + } + } + + if (storageReport.getIps() != null) { + writeTag(7, 2); + writeInt(storageReport.getIps().size()); + + for (String ip : storageReport.getIps()) { + writeString(ip); + } + } + + if (storageReport.getOps() != null) { + writeTag(8, 2); + writeInt(storageReport.getOps().size()); + + for (String op : storageReport.getOps()) { + writeString(op); + } + } + + if (!storageReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(storageReport.getMachines().size()); + + for (Machine machine : storageReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..97120dd3a4 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultNativeParser.java @@ -0,0 +1,367 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.storage.model.IVisitor; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static StorageReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static StorageReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + StorageReport storageReport = new StorageReport(); + + try { + storageReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return storageReport; + } + + @Override + public void visitDomain(Domain domain) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDomainChildren(domain, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDomainChildren(Domain domain, int _field, int _type) { + switch (_field) { + case 1: + domain.setId(readString()); + break; + case 33: + if (_type == 1) { + Operation operation = new Operation(); + + visitOperation(operation); + m_linker.onOperation(domain, operation); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Operation operation = new Operation(); + + visitOperation(operation); + m_linker.onOperation(domain, operation); + } + } + break; + case 34: + if (_type == 1) { + Sql sql = new Sql(); + + visitSql(sql); + m_linker.onSql(domain, sql); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Sql sql = new Sql(); + + visitSql(sql); + m_linker.onSql(domain, sql); + } + } + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setId(readString()); + break; + case 33: + if (_type == 1) { + Domain domain = new Domain(); + + visitDomain(domain); + m_linker.onDomain(machine, domain); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Domain domain = new Domain(); + + visitDomain(domain); + m_linker.onDomain(machine, domain); + } + } + break; + } + } + + @Override + public void visitOperation(Operation operation) { + byte tag; + + while ((tag = readTag()) != -1) { + visitOperationChildren(operation, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitOperationChildren(Operation operation, int _field, int _type) { + switch (_field) { + case 1: + operation.setId(readString()); + break; + case 2: + operation.setCount(readLong()); + break; + case 3: + operation.setAvg(readDouble()); + break; + case 4: + operation.setSum(readDouble()); + break; + case 5: + operation.setError(readLong()); + break; + case 6: + operation.setLongCount(readLong()); + break; + case 33: + if (_type == 1) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(operation, segment); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(operation, segment); + } + } + break; + } + } + + @Override + public void visitSegment(Segment segment) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSegmentChildren(segment, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSegmentChildren(Segment segment, int _field, int _type) { + switch (_field) { + case 1: + segment.setId(readInt()); + break; + case 2: + segment.setCount(readLong()); + break; + case 3: + segment.setAvg(readDouble()); + break; + case 4: + segment.setSum(readDouble()); + break; + case 5: + segment.setError(readLong()); + break; + case 6: + segment.setLongCount(readLong()); + break; + } + } + + @Override + public void visitSql(Sql sql) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSqlChildren(sql, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSqlChildren(Sql sql, int _field, int _type) { + switch (_field) { + case 1: + sql.setId(readString()); + break; + case 2: + sql.setStatement(readString()); + break; + case 3: + sql.setCount(readInt()); + break; + } + } + + @Override + public void visitStorageReport(StorageReport storageReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitStorageReportChildren(storageReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitStorageReportChildren(StorageReport storageReport, int _field, int _type) { + switch (_field) { + case 1: + storageReport.setId(readString()); + break; + case 2: + storageReport.setName(readString()); + break; + case 3: + storageReport.setType(readString()); + break; + case 4: + storageReport.setStartTime(readDate()); + break; + case 5: + storageReport.setEndTime(readDate()); + break; + case 6: + if (_type == 1) { + storageReport.addId(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + storageReport.addId(readString()); + } + } + break; + case 7: + if (_type == 1) { + storageReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + storageReport.addIp(readString()); + } + } + break; + case 8: + if (_type == 1) { + storageReport.addOp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + storageReport.addOp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(storageReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(storageReport, machine); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..44ed3115e1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxMaker.java @@ -0,0 +1,219 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ERROR; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_LONG_COUNT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_STATEMENT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_TYPE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Domain buildDomain(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Domain domain = new Domain(id); + + return domain; + } + + @Override + public String buildId(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Machine machine = new Machine(id); + + return machine; + } + + @Override + public String buildOp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Operation buildOperation(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String error = attributes.getValue(ATTR_ERROR); + String longCount = attributes.getValue(ATTR_LONG_COUNT); + Operation operation = new Operation(id); + + if (count != null) { + operation.setCount(convert(Long.class, count, 0L)); + } + + if (avg != null) { + operation.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (sum != null) { + operation.setSum(toNumber(sum, "0.0", 0).doubleValue()); + } + + if (error != null) { + operation.setError(convert(Long.class, error, 0L)); + } + + if (longCount != null) { + operation.setLongCount(convert(Long.class, longCount, 0L)); + } + + return operation; + } + + @Override + public Segment buildSegment(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String error = attributes.getValue(ATTR_ERROR); + String longCount = attributes.getValue(ATTR_LONG_COUNT); + Segment segment = new Segment(id == null ? 0 : convert(Integer.class, id, 0)); + + if (count != null) { + segment.setCount(convert(Long.class, count, 0L)); + } + + if (avg != null) { + segment.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (sum != null) { + segment.setSum(toNumber(sum, "0.0", 0).doubleValue()); + } + + if (error != null) { + segment.setError(convert(Long.class, error, 0L)); + } + + if (longCount != null) { + segment.setLongCount(convert(Long.class, longCount, 0L)); + } + + return segment; + } + + @Override + public Sql buildSql(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String statement = attributes.getValue(ATTR_STATEMENT); + String count = attributes.getValue(ATTR_COUNT); + Sql sql = new Sql(id); + + if (statement != null) { + sql.setStatement(statement); + } + + if (count != null) { + sql.setCount(convert(Integer.class, count, 0)); + } + + return sql; + } + + @Override + public StorageReport buildStorageReport(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String name = attributes.getValue(ATTR_NAME); + String type = attributes.getValue(ATTR_TYPE); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + StorageReport storageReport = new StorageReport(id); + + if (name != null) { + storageReport.setName(name); + } + + if (type != null) { + storageReport.setType(type); + } + + if (startTime != null) { + storageReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + storageReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return storageReport; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..2b76baea02 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultSaxParser.java @@ -0,0 +1,352 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_IDS; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_IPS; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_OP; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_OPS; + +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_OPERATION; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SQL; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_STORAGE_REPORT; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.storage.model.IEntity; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static StorageReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(StorageReport.class, new InputSource(removeBOM(in))); + } + + public static StorageReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(StorageReport.class, new InputSource(removeBOM(reader))); + } + + public static StorageReport parse(String xml) throws SAXException, IOException { + return parseEntity(StorageReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof StorageReport) { + StorageReport storageReport = (StorageReport) currentObj; + + if (ELEMENT_ID.equals(currentTag)) { + storageReport.addId(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + storageReport.addIp(getText()); + } else if (ELEMENT_OP.equals(currentTag)) { + storageReport.addOp(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_OPERATION.equals(qName)) { + Operation operation = m_maker.buildOperation(attributes); + + m_linker.onOperation(parentObj, operation); + m_objs.push(operation); + } else if (ENTITY_SQL.equals(qName)) { + Sql sql = m_maker.buildSql(attributes); + + m_linker.onSql(parentObj, sql); + m_objs.push(sql); + } else { + throw new SAXException(String.format("Element(%s) is not expected under domain!", qName)); + } + + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForOperation(Operation parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_linker.onSegment(parentObj, segment); + m_objs.push(segment); + } else { + throw new SAXException(String.format("Element(%s) is not expected under operation!", qName)); + } + + m_tags.push(qName); + } + + private void parseForSegment(Segment parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForSql(Sql parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForStorageReport(StorageReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_IDS.equals(qName) || ELEMENT_ID.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName) || ELEMENT_OPS.equals(qName) || ELEMENT_OP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under storage-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_STORAGE_REPORT.equals(qName)) { + StorageReport storageReport = m_maker.buildStorageReport(attributes); + + m_entity = storageReport; + m_objs.push(storageReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else if (ENTITY_OPERATION.equals(qName)) { + Operation operation = m_maker.buildOperation(attributes); + + m_entity = operation; + m_objs.push(operation); + m_tags.push(qName); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_entity = segment; + m_objs.push(segment); + m_tags.push(qName); + } else if (ENTITY_SQL.equals(qName)) { + Sql sql = m_maker.buildSql(attributes); + + m_entity = sql; + m_objs.push(sql); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof StorageReport) { + parseForStorageReport((StorageReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else if (parent instanceof Operation) { + parseForOperation((Operation) parent, tag, qName, attributes); + } else if (parent instanceof Segment) { + parseForSegment((Segment) parent, tag, qName, attributes); + } else if (parent instanceof Sql) { + parseForSql((Sql) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..902f3f42fe --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,360 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ERROR; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_LONG_COUNT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_STATEMENT; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.storage.model.Constants.ATTR_TYPE; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_ID; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.storage.model.Constants.ELEMENT_OP; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_OPERATION; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_SQL; +import static com.dianping.cat.consumer.storage.model.Constants.ENTITY_STORAGE_REPORT; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.storage.model.IEntity; +import com.dianping.cat.consumer.storage.model.IVisitor; +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, null, ATTR_ID, domain.getId()); + + if (!domain.getOperations().isEmpty()) { + for (Operation operation : domain.getOperations().values()) { + operation.accept(m_visitor); + } + } + + if (!domain.getSqls().isEmpty()) { + for (Sql sql : domain.getSqls().values()) { + sql.accept(m_visitor); + } + } + + endTag(ENTITY_DOMAIN); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_ID, machine.getId()); + + if (!machine.getDomains().isEmpty()) { + for (Domain domain : machine.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitOperation(Operation operation) { + startTag(ENTITY_OPERATION, null, ATTR_ID, operation.getId(), ATTR_COUNT, operation.getCount(), ATTR_AVG, toString(operation.getAvg(), "0.0"), ATTR_SUM, toString(operation.getSum(), "0.0"), ATTR_ERROR, operation.getError(), ATTR_LONG_COUNT, operation.getLongCount()); + + if (!operation.getSegments().isEmpty()) { + for (Segment segment : operation.getSegments().values()) { + segment.accept(m_visitor); + } + } + + endTag(ENTITY_OPERATION); + } + + @Override + public void visitSegment(Segment segment) { + startTag(ENTITY_SEGMENT, true, null, ATTR_ID, segment.getId(), ATTR_COUNT, segment.getCount(), ATTR_AVG, toString(segment.getAvg(), "0.0"), ATTR_SUM, toString(segment.getSum(), "0.0"), ATTR_ERROR, segment.getError(), ATTR_LONG_COUNT, segment.getLongCount()); + } + + @Override + public void visitSql(Sql sql) { + startTag(ENTITY_SQL, true, null, ATTR_ID, sql.getId(), ATTR_STATEMENT, sql.getStatement(), ATTR_COUNT, sql.getCount()); + } + + @Override + public void visitStorageReport(StorageReport storageReport) { + startTag(ENTITY_STORAGE_REPORT, null, ATTR_ID, storageReport.getId(), ATTR_NAME, storageReport.getName(), ATTR_TYPE, storageReport.getType(), ATTR_STARTTIME, toString(storageReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(storageReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!storageReport.getIds().isEmpty()) { + for (String id : storageReport.getIds()) { + tagWithText(ELEMENT_ID, id); + } + } + + if (!storageReport.getIps().isEmpty()) { + for (String ip : storageReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!storageReport.getOps().isEmpty()) { + for (String op : storageReport.getOps()) { + tagWithText(ELEMENT_OP, op); + } + } + + if (!storageReport.getMachines().isEmpty()) { + for (Machine machine : storageReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_STORAGE_REPORT); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/ILinker.java new file mode 100644 index 0000000000..cec66c70c6 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/ILinker.java @@ -0,0 +1,21 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public interface ILinker { + + public boolean onDomain(Machine parent, Domain domain); + + public boolean onMachine(StorageReport parent, Machine machine); + + public boolean onOperation(Domain parent, Operation operation); + + public boolean onSegment(Operation parent, Segment segment); + + public boolean onSql(Domain parent, Sql sql); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IMaker.java new file mode 100644 index 0000000000..be137c45be --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IMaker.java @@ -0,0 +1,29 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public interface IMaker { + + public Domain buildDomain(T node); + + public String buildId(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public String buildOp(T node); + + public Operation buildOperation(T node); + + public Segment buildSegment(T node); + + public Sql buildSql(T node); + + public StorageReport buildStorageReport(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IParser.java new file mode 100644 index 0000000000..c19be9b083 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/storage/model/transform/IParser.java @@ -0,0 +1,22 @@ +package com.dianping.cat.consumer.storage.model.transform; + +import com.dianping.cat.consumer.storage.model.entity.Domain; +import com.dianping.cat.consumer.storage.model.entity.Machine; +import com.dianping.cat.consumer.storage.model.entity.Operation; +import com.dianping.cat.consumer.storage.model.entity.Segment; +import com.dianping.cat.consumer.storage.model.entity.Sql; +import com.dianping.cat.consumer.storage.model.entity.StorageReport; + +public interface IParser { + public StorageReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForOperation(IMaker maker, ILinker linker, Operation parent, T node); + + public void parseForSegment(IMaker maker, ILinker linker, Segment parent, T node); + + public void parseForSql(IMaker maker, ILinker linker, Sql parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopAnalyzer.java index 375fef450c..dffcb57f30 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopAnalyzer.java @@ -18,19 +18,16 @@ */ package com.dianping.cat.consumer.top; -import java.util.HashSet; import java.util.List; import java.util.Set; - -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Splitters; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import java.util.stream.Collectors; +import java.util.stream.Stream; import com.dianping.cat.Constants; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.consumer.top.model.entity.Segment; import com.dianping.cat.consumer.top.model.entity.TopReport; @@ -38,43 +35,43 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; - -@Named(type = MessageAnalyzer.class, value = TopAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class TopAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + TopAnalyzer.ID) +@Scope("prototype") +public class TopAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "top"; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = TopAnalyzer.ID + "ReportManager") + private ReportManager topReportManager; - @Inject - private ServerFilterConfigManager m_serverFilterConfigManager; + @Resource(name = "serverFilterConfigManager") + private ServerFilterConfigManager serverFilterConfigManager; - private Set m_errorTypes; + private Set errorTypes; @Override public synchronized void doCheckpoint(boolean atEnd) { long startTime = getStartTime(); if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(startTime, StoragePolicy.FILE_AND_DB, m_index); + topReportManager.storeHourlyReports(startTime, StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(startTime, StoragePolicy.FILE, m_index); + topReportManager.storeHourlyReports(startTime, StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public TopReport getReport(String domain) { - return m_reportManager.getHourlyReport(getStartTime(), Constants.CAT, false); + return topReportManager.getHourlyReport(getStartTime(), Constants.CAT, false); } @Override public ReportManager getReportManager() { - return m_reportManager; + return topReportManager; } @Override @@ -88,15 +85,15 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + topReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } @Override public void process(MessageTree tree) { String domain = tree.getDomain(); - if (m_serverFilterConfigManager.validateDomain(domain)) { - TopReport report = m_reportManager.getHourlyReport(getStartTime(), Constants.CAT, true); + if (serverFilterConfigManager.validateDomain(domain)) { + TopReport report = topReportManager.getHourlyReport(getStartTime(), Constants.CAT, true); List events = tree.getEvents(); @@ -109,7 +106,7 @@ public void process(MessageTree tree) { private void processEvent(TopReport report, MessageTree tree, Event event) { String type = event.getType(); - if (m_errorTypes.contains(type)) { + if (errorTypes.contains(type)) { String domain = tree.getDomain(); String ip = tree.getIpAddress(); String exception = event.getName(); @@ -122,7 +119,22 @@ private void processEvent(TopReport report, MessageTree tree, Event event) { } } + @Value("Error,RuntimeException,Exception") public void setErrorType(String type) { - m_errorTypes = new HashSet(Splitters.by(',').noEmptyItem().split(type)); + errorTypes = Stream.of(type.split(",")).map(String::trim).filter(item -> !item.isEmpty()).collect(Collectors.toSet()); + } + + public void setReportManager(ReportManager reportManager) { + topReportManager = reportManager; + } + + public void setServerFilterConfigManager(ServerFilterConfigManager serverFilterConfigManager) { + this.serverFilterConfigManager = serverFilterConfigManager; + } + + @Override + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); } -} \ No newline at end of file +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopDelegate.java index 5941f08ad6..4da47d94d4 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/TopDelegate.java @@ -23,12 +23,10 @@ import com.dianping.cat.consumer.top.model.transform.DefaultNativeParser; import com.dianping.cat.consumer.top.model.transform.DefaultSaxParser; import com.dianping.cat.report.ReportDelegate; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = TopAnalyzer.ID) public class TopDelegate implements ReportDelegate { @Override diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/BaseEntity.java new file mode 100644 index 0000000000..85001f1e05 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.top.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.top.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/Constants.java new file mode 100644 index 0000000000..5d8b5017dd --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/Constants.java @@ -0,0 +1,76 @@ +package com.dianping.cat.consumer.top.model; + +public class Constants { + + public static final String ATTR_CACHE = "cache"; + + public static final String ATTR_CACHE_DURATION = "cache-duration"; + + public static final String ATTR_CACHE_ERROR = "cache-error"; + + public static final String ATTR_CACHE_SUM = "cache-sum"; + + public static final String ATTR_CALL = "call"; + + public static final String ATTR_CALL_DURATION = "call-duration"; + + public static final String ATTR_CALL_ERROR = "call-error"; + + public static final String ATTR_CALL_SUM = "call-sum"; + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_ERROR = "error"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_SERVICE = "service"; + + public static final String ATTR_SERVICE_DURATION = "service-duration"; + + public static final String ATTR_SERVICE_ERROR = "service-error"; + + public static final String ATTR_SERVICE_SUM = "service-sum"; + + public static final String ATTR_SQL = "sql"; + + public static final String ATTR_SQL_DURATION = "sql-duration"; + + public static final String ATTR_SQL_ERROR = "sql-error"; + + public static final String ATTR_SQL_SUM = "sql-sum"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_URL = "url"; + + public static final String ATTR_URL_DURATION = "url-duration"; + + public static final String ATTR_URL_ERROR = "url-error"; + + public static final String ATTR_URL_SUM = "url-sum"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_ERROR = "error"; + + public static final String ENTITY_ERRORS = "errors"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_SEGMENT = "segment"; + + public static final String ENTITY_SEGMENTS = "segments"; + + public static final String ENTITY_TOP_REPORT = "top-report"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IEntity.java new file mode 100644 index 0000000000..0db52a06cb --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.top.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IVisitor.java new file mode 100644 index 0000000000..7594a3f384 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/IVisitor.java @@ -0,0 +1,20 @@ +package com.dianping.cat.consumer.top.model; + +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public interface IVisitor { + + public void visitDomain(Domain domain); + + public void visitError(Error error); + + public void visitMachine(Machine machine); + + public void visitSegment(Segment segment); + + public void visitTopReport(TopReport topReport); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Domain.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Domain.java new file mode 100644 index 0000000000..e3fb2b4a27 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Domain.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.top.model.entity; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_DOMAIN; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.top.model.BaseEntity; +import com.dianping.cat.consumer.top.model.IVisitor; + +public class Domain extends BaseEntity { + private String m_name; + + private Map m_segments = new LinkedHashMap(); + + public Domain() { + } + + public Domain(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + public Domain addSegment(Segment segment) { + m_segments.put(segment.getId(), segment); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public Segment findSegment(Integer id) { + return m_segments.get(id); + } + + public Segment findOrCreateSegment(Integer id) { + Segment segment = m_segments.get(id); + + if (segment == null) { + synchronized (m_segments) { + segment = m_segments.get(id); + + if (segment == null) { + segment = new Segment(id); + m_segments.put(id, segment); + } + } + } + + return segment; + } + + public String getName() { + return m_name; + } + + public Map getSegments() { + return m_segments; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_NAME, m_name, other.getName()); + + } + + public Segment removeSegment(Integer id) { + return m_segments.remove(id); + } + + public Domain setName(String name) { + m_name = name; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Error.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Error.java new file mode 100644 index 0000000000..ee5b8726cc --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Error.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.top.model.entity; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_ERROR; + +import com.dianping.cat.consumer.top.model.BaseEntity; +import com.dianping.cat.consumer.top.model.IVisitor; + +public class Error extends BaseEntity { + private String m_id; + + private int m_count; + + public Error() { + } + + public Error(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitError(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Error) { + Error _o = (Error) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Error incCount() { + m_count++; + return this; + } + + public Error incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Error other) { + assertAttributeEquals(other, ENTITY_ERROR, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + } + + public Error setCount(int count) { + m_count = count; + return this; + } + + public Error setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Machine.java new file mode 100644 index 0000000000..e71b09e023 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Machine.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.top.model.entity; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_MACHINE; + +import com.dianping.cat.consumer.top.model.BaseEntity; +import com.dianping.cat.consumer.top.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_id; + + private int m_count; + + public Machine() { + } + + public Machine(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Machine incCount() { + m_count++; + return this; + } + + public Machine incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + } + + public Machine setCount(int count) { + m_count = count; + return this; + } + + public Machine setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Segment.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Segment.java new file mode 100644 index 0000000000..68bf342d27 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/Segment.java @@ -0,0 +1,420 @@ +package com.dianping.cat.consumer.top.model.entity; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_SEGMENT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.top.model.BaseEntity; +import com.dianping.cat.consumer.top.model.IVisitor; + +public class Segment extends BaseEntity { + private Integer m_id; + + private long m_error; + + private long m_url; + + private double m_urlDuration; + + private long m_service; + + private double m_serviceDuration; + + private long m_sql; + + private double m_sqlDuration; + + private long m_call; + + private double m_callDuration; + + private long m_cache; + + private double m_cacheDuration; + + private long m_urlError; + + private double m_urlSum; + + private long m_serviceError; + + private double m_serviceSum; + + private long m_sqlError; + + private double m_sqlSum; + + private long m_callError; + + private double m_callSum; + + private long m_cacheError; + + private double m_cacheSum; + + private Map m_errors = new LinkedHashMap(); + + private Map m_machines = new LinkedHashMap(); + + public Segment() { + } + + public Segment(Integer id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSegment(this); + } + + public Segment addError(Error error) { + m_errors.put(error.getId(), error); + return this; + } + + public Segment addMachine(Machine machine) { + m_machines.put(machine.getId(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Segment) { + Segment _o = (Segment) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Error findError(String id) { + return m_errors.get(id); + } + + public Machine findMachine(String id) { + return m_machines.get(id); + } + + public Error findOrCreateError(String id) { + Error error = m_errors.get(id); + + if (error == null) { + synchronized (m_errors) { + error = m_errors.get(id); + + if (error == null) { + error = new Error(id); + m_errors.put(id, error); + } + } + } + + return error; + } + + public Machine findOrCreateMachine(String id) { + Machine machine = m_machines.get(id); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(id); + + if (machine == null) { + machine = new Machine(id); + m_machines.put(id, machine); + } + } + } + + return machine; + } + + public long getCache() { + return m_cache; + } + + public double getCacheDuration() { + return m_cacheDuration; + } + + public long getCacheError() { + return m_cacheError; + } + + public double getCacheSum() { + return m_cacheSum; + } + + public long getCall() { + return m_call; + } + + public double getCallDuration() { + return m_callDuration; + } + + public long getCallError() { + return m_callError; + } + + public double getCallSum() { + return m_callSum; + } + + public long getError() { + return m_error; + } + + public Map getErrors() { + return m_errors; + } + + public Integer getId() { + return m_id; + } + + public Map getMachines() { + return m_machines; + } + + public long getService() { + return m_service; + } + + public double getServiceDuration() { + return m_serviceDuration; + } + + public long getServiceError() { + return m_serviceError; + } + + public double getServiceSum() { + return m_serviceSum; + } + + public long getSql() { + return m_sql; + } + + public double getSqlDuration() { + return m_sqlDuration; + } + + public long getSqlError() { + return m_sqlError; + } + + public double getSqlSum() { + return m_sqlSum; + } + + public long getUrl() { + return m_url; + } + + public double getUrlDuration() { + return m_urlDuration; + } + + public long getUrlError() { + return m_urlError; + } + + public double getUrlSum() { + return m_urlSum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public Segment incError() { + m_error++; + return this; + } + + public Segment incError(long error) { + m_error += error; + return this; + } + + @Override + public void mergeAttributes(Segment other) { + assertAttributeEquals(other, ENTITY_SEGMENT, ATTR_ID, m_id, other.getId()); + + m_error = other.getError(); + + m_url = other.getUrl(); + + m_urlDuration = other.getUrlDuration(); + + m_service = other.getService(); + + m_serviceDuration = other.getServiceDuration(); + + m_sql = other.getSql(); + + m_sqlDuration = other.getSqlDuration(); + + m_call = other.getCall(); + + m_callDuration = other.getCallDuration(); + + m_cache = other.getCache(); + + m_cacheDuration = other.getCacheDuration(); + + m_urlError = other.getUrlError(); + + m_urlSum = other.getUrlSum(); + + m_serviceError = other.getServiceError(); + + m_serviceSum = other.getServiceSum(); + + m_sqlError = other.getSqlError(); + + m_sqlSum = other.getSqlSum(); + + m_callError = other.getCallError(); + + m_callSum = other.getCallSum(); + + m_cacheError = other.getCacheError(); + + m_cacheSum = other.getCacheSum(); + } + + public Error removeError(String id) { + return m_errors.remove(id); + } + + public Machine removeMachine(String id) { + return m_machines.remove(id); + } + + public Segment setCache(long cache) { + m_cache = cache; + return this; + } + + public Segment setCacheDuration(double cacheDuration) { + m_cacheDuration = cacheDuration; + return this; + } + + public Segment setCacheError(long cacheError) { + m_cacheError = cacheError; + return this; + } + + public Segment setCacheSum(double cacheSum) { + m_cacheSum = cacheSum; + return this; + } + + public Segment setCall(long call) { + m_call = call; + return this; + } + + public Segment setCallDuration(double callDuration) { + m_callDuration = callDuration; + return this; + } + + public Segment setCallError(long callError) { + m_callError = callError; + return this; + } + + public Segment setCallSum(double callSum) { + m_callSum = callSum; + return this; + } + + public Segment setError(long error) { + m_error = error; + return this; + } + + public Segment setId(Integer id) { + m_id = id; + return this; + } + + public Segment setService(long service) { + m_service = service; + return this; + } + + public Segment setServiceDuration(double serviceDuration) { + m_serviceDuration = serviceDuration; + return this; + } + + public Segment setServiceError(long serviceError) { + m_serviceError = serviceError; + return this; + } + + public Segment setServiceSum(double serviceSum) { + m_serviceSum = serviceSum; + return this; + } + + public Segment setSql(long sql) { + m_sql = sql; + return this; + } + + public Segment setSqlDuration(double sqlDuration) { + m_sqlDuration = sqlDuration; + return this; + } + + public Segment setSqlError(long sqlError) { + m_sqlError = sqlError; + return this; + } + + public Segment setSqlSum(double sqlSum) { + m_sqlSum = sqlSum; + return this; + } + + public Segment setUrl(long url) { + m_url = url; + return this; + } + + public Segment setUrlDuration(double urlDuration) { + m_urlDuration = urlDuration; + return this; + } + + public Segment setUrlError(long urlError) { + m_urlError = urlError; + return this; + } + + public Segment setUrlSum(double urlSum) { + m_urlSum = urlSum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/TopReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/TopReport.java new file mode 100644 index 0000000000..097e0861ee --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/entity/TopReport.java @@ -0,0 +1,131 @@ +package com.dianping.cat.consumer.top.model.entity; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_TOP_REPORT; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.consumer.top.model.BaseEntity; +import com.dianping.cat.consumer.top.model.IVisitor; + +public class TopReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Map m_domains = new LinkedHashMap(); + + public TopReport() { + } + + public TopReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitTopReport(this); + } + + public TopReport addDomain(Domain domain) { + m_domains.put(domain.getName(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TopReport) { + TopReport _o = (TopReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Domain findDomain(String name) { + return m_domains.get(name); + } + + public Domain findOrCreateDomain(String name) { + Domain domain = m_domains.get(name); + + if (domain == null) { + synchronized (m_domains) { + domain = m_domains.get(name); + + if (domain == null) { + domain = new Domain(name); + m_domains.put(name, domain); + } + } + } + + return domain; + } + + public String getDomain() { + return m_domain; + } + + public Map getDomains() { + return m_domains; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(TopReport other) { + assertAttributeEquals(other, ENTITY_TOP_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Domain removeDomain(String name) { + return m_domains.remove(name); + } + + public TopReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public TopReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public TopReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..2fd4b9a7bc --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/BaseVisitor.java @@ -0,0 +1,43 @@ +package com.dianping.cat.consumer.top.model.transform; + +import com.dianping.cat.consumer.top.model.IVisitor; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitDomain(Domain domain) { + for (Segment segment : domain.getSegments().values()) { + visitSegment(segment); + } + } + + @Override + public void visitError(Error error) { + } + + @Override + public void visitMachine(Machine machine) { + } + + @Override + public void visitSegment(Segment segment) { + for (Error error : segment.getErrors().values()) { + visitError(error); + } + + for (Machine machine : segment.getMachines().values()) { + visitMachine(machine); + } + } + + @Override + public void visitTopReport(TopReport topReport) { + for (Domain domain : topReport.getDomains().values()) { + visitDomain(domain); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..4c01206177 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultLinker.java @@ -0,0 +1,89 @@ +package com.dianping.cat.consumer.top.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDomain(final TopReport parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } + + @Override + public boolean onError(final Segment parent, final Error error) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addError(error); + } + }); + } else { + parent.addError(error); + } + + return true; + } + + @Override + public boolean onMachine(final Segment parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onSegment(final Domain parent, final Segment segment) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addSegment(segment); + } + }); + } else { + parent.addSegment(segment); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..52262c8c2d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultMerger.java @@ -0,0 +1,164 @@ +package com.dianping.cat.consumer.top.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.top.model.IEntity; +import com.dianping.cat.consumer.top.model.IVisitor; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private TopReport m_topReport; + + public DefaultMerger() { + } + + public DefaultMerger(TopReport topReport) { + m_topReport = topReport; + m_objs.push(topReport); + } + + public TopReport getTopReport() { + return m_topReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeDomain(Domain to, Domain from) { + to.mergeAttributes(from); + } + + protected void mergeError(Error to, Error from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeSegment(Segment to, Segment from) { + to.mergeAttributes(from); + } + + protected void mergeTopReport(TopReport to, TopReport from) { + to.mergeAttributes(from); + } + + @Override + public void visitDomain(Domain from) { + Domain to = (Domain) m_objs.peek(); + + mergeDomain(to, from); + visitDomainChildren(to, from); + } + + protected void visitDomainChildren(Domain to, Domain from) { + for (Segment source : from.getSegments().values()) { + Segment target = to.findSegment(source.getId()); + + if (target == null) { + target = new Segment(source.getId()); + to.addSegment(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitError(Error from) { + Error to = (Error) m_objs.peek(); + + mergeError(to, from); + visitErrorChildren(to, from); + } + + protected void visitErrorChildren(Error to, Error from) { + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + } + + @Override + public void visitSegment(Segment from) { + Segment to = (Segment) m_objs.peek(); + + mergeSegment(to, from); + visitSegmentChildren(to, from); + } + + protected void visitSegmentChildren(Segment to, Segment from) { + for (Error source : from.getErrors().values()) { + Error target = to.findError(source.getId()); + + if (target == null) { + target = new Error(source.getId()); + to.addError(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getId()); + + if (target == null) { + target = new Machine(source.getId()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitTopReport(TopReport from) { + TopReport to = (TopReport) m_objs.peek(); + + mergeTopReport(to, from); + visitTopReportChildren(to, from); + } + + protected void visitTopReportChildren(TopReport to, TopReport from) { + for (Domain source : from.getDomains().values()) { + Domain target = to.findDomain(source.getName()); + + if (target == null) { + target = new Domain(source.getName()); + to.addDomain(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..4e6f3f3be3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,267 @@ +package com.dianping.cat.consumer.top.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.consumer.top.model.IVisitor; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(TopReport topReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(topReport, out); + return out.toByteArray(); + } + + public static void build(TopReport topReport, OutputStream out) { + topReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitDomain(Domain domain) { + if (domain.getName() != null) { + writeTag(1, 1); + writeString(domain.getName()); + } + + if (!domain.getSegments().isEmpty()) { + writeTag(33, 2); + writeInt(domain.getSegments().size()); + + for (Segment segment : domain.getSegments().values()) { + segment.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitError(Error error) { + if (error.getId() != null) { + writeTag(1, 1); + writeString(error.getId()); + } + + writeTag(2, 0); + writeInt(error.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getId() != null) { + writeTag(1, 1); + writeString(machine.getId()); + } + + writeTag(2, 0); + writeInt(machine.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitSegment(Segment segment) { + if (segment.getId() != null) { + writeTag(1, 1); + writeInt(segment.getId()); + } + + writeTag(2, 0); + writeLong(segment.getError()); + + writeTag(3, 0); + writeLong(segment.getUrl()); + + writeTag(4, 0); + writeDouble(segment.getUrlDuration()); + + writeTag(5, 0); + writeLong(segment.getService()); + + writeTag(6, 0); + writeDouble(segment.getServiceDuration()); + + writeTag(7, 0); + writeLong(segment.getSql()); + + writeTag(8, 0); + writeDouble(segment.getSqlDuration()); + + writeTag(9, 0); + writeLong(segment.getCall()); + + writeTag(10, 0); + writeDouble(segment.getCallDuration()); + + writeTag(11, 0); + writeLong(segment.getCache()); + + writeTag(12, 0); + writeDouble(segment.getCacheDuration()); + + writeTag(13, 0); + writeLong(segment.getUrlError()); + + writeTag(14, 0); + writeDouble(segment.getUrlSum()); + + writeTag(15, 0); + writeLong(segment.getServiceError()); + + writeTag(16, 0); + writeDouble(segment.getServiceSum()); + + writeTag(17, 0); + writeLong(segment.getSqlError()); + + writeTag(18, 0); + writeDouble(segment.getSqlSum()); + + writeTag(19, 0); + writeLong(segment.getCallError()); + + writeTag(20, 0); + writeDouble(segment.getCallSum()); + + writeTag(21, 0); + writeLong(segment.getCacheError()); + + writeTag(22, 0); + writeDouble(segment.getCacheSum()); + + if (!segment.getErrors().isEmpty()) { + writeTag(33, 2); + writeInt(segment.getErrors().size()); + + for (Error error : segment.getErrors().values()) { + error.accept(m_visitor); + } + } + + if (!segment.getMachines().isEmpty()) { + writeTag(34, 2); + writeInt(segment.getMachines().size()); + + for (Machine machine : segment.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitTopReport(TopReport topReport) { + writeTag(63, 0); + + if (topReport.getDomain() != null) { + writeTag(1, 1); + writeString(topReport.getDomain()); + } + + if (topReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(topReport.getStartTime()); + } + + if (topReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(topReport.getEndTime()); + } + + if (!topReport.getDomains().isEmpty()) { + writeTag(33, 2); + writeInt(topReport.getDomains().size()); + + for (Domain domain : topReport.getDomains().values()) { + domain.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..96ebff7b32 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultNativeParser.java @@ -0,0 +1,334 @@ +package com.dianping.cat.consumer.top.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.consumer.top.model.IVisitor; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static TopReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static TopReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + TopReport topReport = new TopReport(); + + try { + topReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return topReport; + } + + @Override + public void visitDomain(Domain domain) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDomainChildren(domain, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDomainChildren(Domain domain, int _field, int _type) { + switch (_field) { + case 1: + domain.setName(readString()); + break; + case 33: + if (_type == 1) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(domain, segment); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Segment segment = new Segment(); + + visitSegment(segment); + m_linker.onSegment(domain, segment); + } + } + break; + } + } + + @Override + public void visitError(Error error) { + byte tag; + + while ((tag = readTag()) != -1) { + visitErrorChildren(error, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitErrorChildren(Error error, int _field, int _type) { + switch (_field) { + case 1: + error.setId(readString()); + break; + case 2: + error.setCount(readInt()); + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setId(readString()); + break; + case 2: + machine.setCount(readInt()); + break; + } + } + + @Override + public void visitSegment(Segment segment) { + byte tag; + + while ((tag = readTag()) != -1) { + visitSegmentChildren(segment, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitSegmentChildren(Segment segment, int _field, int _type) { + switch (_field) { + case 1: + segment.setId(readInt()); + break; + case 2: + segment.setError(readLong()); + break; + case 3: + segment.setUrl(readLong()); + break; + case 4: + segment.setUrlDuration(readDouble()); + break; + case 5: + segment.setService(readLong()); + break; + case 6: + segment.setServiceDuration(readDouble()); + break; + case 7: + segment.setSql(readLong()); + break; + case 8: + segment.setSqlDuration(readDouble()); + break; + case 9: + segment.setCall(readLong()); + break; + case 10: + segment.setCallDuration(readDouble()); + break; + case 11: + segment.setCache(readLong()); + break; + case 12: + segment.setCacheDuration(readDouble()); + break; + case 13: + segment.setUrlError(readLong()); + break; + case 14: + segment.setUrlSum(readDouble()); + break; + case 15: + segment.setServiceError(readLong()); + break; + case 16: + segment.setServiceSum(readDouble()); + break; + case 17: + segment.setSqlError(readLong()); + break; + case 18: + segment.setSqlSum(readDouble()); + break; + case 19: + segment.setCallError(readLong()); + break; + case 20: + segment.setCallSum(readDouble()); + break; + case 21: + segment.setCacheError(readLong()); + break; + case 22: + segment.setCacheSum(readDouble()); + break; + case 33: + if (_type == 1) { + Error error = new Error(); + + visitError(error); + m_linker.onError(segment, error); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Error error = new Error(); + + visitError(error); + m_linker.onError(segment, error); + } + } + break; + case 34: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(segment, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(segment, machine); + } + } + break; + } + } + + @Override + public void visitTopReport(TopReport topReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitTopReportChildren(topReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitTopReportChildren(TopReport topReport, int _field, int _type) { + switch (_field) { + case 1: + topReport.setDomain(readString()); + break; + case 2: + topReport.setStartTime(readDate()); + break; + case 3: + topReport.setEndTime(readDate()); + break; + case 33: + if (_type == 1) { + Domain domain = new Domain(); + + visitDomain(domain); + m_linker.onDomain(topReport, domain); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Domain domain = new Domain(); + + visitDomain(domain); + m_linker.onDomain(topReport, domain); + } + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..6cb9793291 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxMaker.java @@ -0,0 +1,256 @@ +package com.dianping.cat.consumer.top.model.transform; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_SUM; + +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Domain buildDomain(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + Domain domain = new Domain(name); + + return domain; + } + + @Override + public Error buildError(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + Error error = new Error(id); + + if (count != null) { + error.setCount(convert(Integer.class, count, 0)); + } + + return error; + } + + @Override + public Machine buildMachine(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + Machine machine = new Machine(id); + + if (count != null) { + machine.setCount(convert(Integer.class, count, 0)); + } + + return machine; + } + + @Override + public Segment buildSegment(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String error = attributes.getValue(ATTR_ERROR); + String url = attributes.getValue(ATTR_URL); + String urlDuration = attributes.getValue(ATTR_URL_DURATION); + String service = attributes.getValue(ATTR_SERVICE); + String serviceDuration = attributes.getValue(ATTR_SERVICE_DURATION); + String sql = attributes.getValue(ATTR_SQL); + String sqlDuration = attributes.getValue(ATTR_SQL_DURATION); + String call = attributes.getValue(ATTR_CALL); + String callDuration = attributes.getValue(ATTR_CALL_DURATION); + String cache = attributes.getValue(ATTR_CACHE); + String cacheDuration = attributes.getValue(ATTR_CACHE_DURATION); + String urlError = attributes.getValue(ATTR_URL_ERROR); + String urlSum = attributes.getValue(ATTR_URL_SUM); + String serviceError = attributes.getValue(ATTR_SERVICE_ERROR); + String serviceSum = attributes.getValue(ATTR_SERVICE_SUM); + String sqlError = attributes.getValue(ATTR_SQL_ERROR); + String sqlSum = attributes.getValue(ATTR_SQL_SUM); + String callError = attributes.getValue(ATTR_CALL_ERROR); + String callSum = attributes.getValue(ATTR_CALL_SUM); + String cacheError = attributes.getValue(ATTR_CACHE_ERROR); + String cacheSum = attributes.getValue(ATTR_CACHE_SUM); + Segment segment = new Segment(id == null ? null : convert(Integer.class, id, null)); + + if (error != null) { + segment.setError(convert(Long.class, error, 0L)); + } + + if (url != null) { + segment.setUrl(convert(Long.class, url, 0L)); + } + + if (urlDuration != null) { + segment.setUrlDuration(toNumber(urlDuration, "0.00", 0).doubleValue()); + } + + if (service != null) { + segment.setService(convert(Long.class, service, 0L)); + } + + if (serviceDuration != null) { + segment.setServiceDuration(toNumber(serviceDuration, "0.00", 0).doubleValue()); + } + + if (sql != null) { + segment.setSql(convert(Long.class, sql, 0L)); + } + + if (sqlDuration != null) { + segment.setSqlDuration(toNumber(sqlDuration, "0.00", 0).doubleValue()); + } + + if (call != null) { + segment.setCall(convert(Long.class, call, 0L)); + } + + if (callDuration != null) { + segment.setCallDuration(toNumber(callDuration, "0.00", 0).doubleValue()); + } + + if (cache != null) { + segment.setCache(convert(Long.class, cache, 0L)); + } + + if (cacheDuration != null) { + segment.setCacheDuration(toNumber(cacheDuration, "0.00", 0).doubleValue()); + } + + if (urlError != null) { + segment.setUrlError(convert(Long.class, urlError, 0L)); + } + + if (urlSum != null) { + segment.setUrlSum(toNumber(urlSum, "0.00", 0).doubleValue()); + } + + if (serviceError != null) { + segment.setServiceError(convert(Long.class, serviceError, 0L)); + } + + if (serviceSum != null) { + segment.setServiceSum(toNumber(serviceSum, "0.00", 0).doubleValue()); + } + + if (sqlError != null) { + segment.setSqlError(convert(Long.class, sqlError, 0L)); + } + + if (sqlSum != null) { + segment.setSqlSum(toNumber(sqlSum, "0.00", 0).doubleValue()); + } + + if (callError != null) { + segment.setCallError(convert(Long.class, callError, 0L)); + } + + if (callSum != null) { + segment.setCallSum(toNumber(callSum, "0.00", 0).doubleValue()); + } + + if (cacheError != null) { + segment.setCacheError(convert(Long.class, cacheError, 0L)); + } + + if (cacheSum != null) { + segment.setCacheSum(toNumber(cacheSum, "0.00", 0).doubleValue()); + } + + return segment; + } + + @Override + public TopReport buildTopReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + TopReport topReport = new TopReport(domain); + + if (startTime != null) { + topReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + topReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return topReport; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..4e8b2d0e61 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultSaxParser.java @@ -0,0 +1,309 @@ +package com.dianping.cat.consumer.top.model.transform; + +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_TOP_REPORT; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.top.model.IEntity; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static TopReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(TopReport.class, new InputSource(removeBOM(in))); + } + + public static TopReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(TopReport.class, new InputSource(removeBOM(reader))); + } + + public static TopReport parse(String xml) throws SAXException, IOException { + return parseEntity(TopReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_linker.onSegment(parentObj, segment); + m_objs.push(segment); + } else { + throw new SAXException(String.format("Element(%s) is not expected under domain!", qName)); + } + + m_tags.push(qName); + } + + private void parseForError(Error parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForSegment(Segment parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_ERROR.equals(qName)) { + Error error = m_maker.buildError(attributes); + + m_linker.onError(parentObj, error); + m_objs.push(error); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under segment!", qName)); + } + + m_tags.push(qName); + } + + private void parseForTopReport(TopReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under top-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_TOP_REPORT.equals(qName)) { + TopReport topReport = m_maker.buildTopReport(attributes); + + m_entity = topReport; + m_objs.push(topReport); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else if (ENTITY_SEGMENT.equals(qName)) { + Segment segment = m_maker.buildSegment(attributes); + + m_entity = segment; + m_objs.push(segment); + m_tags.push(qName); + } else if (ENTITY_ERROR.equals(qName)) { + Error error = m_maker.buildError(attributes); + + m_entity = error; + m_objs.push(error); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof TopReport) { + parseForTopReport((TopReport) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else if (parent instanceof Segment) { + parseForSegment((Segment) parent, tag, qName, attributes); + } else if (parent instanceof Error) { + parseForError((Error) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..11ad3a8eea --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,297 @@ +package com.dianping.cat.consumer.top.model.transform; + +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CACHE_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_CALL_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_NAME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SERVICE_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_SQL_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_DURATION; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ATTR_URL_SUM; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_ERROR; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_SEGMENT; +import static com.dianping.cat.consumer.top.model.Constants.ENTITY_TOP_REPORT; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.top.model.IEntity; +import com.dianping.cat.consumer.top.model.IVisitor; +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, null, ATTR_NAME, domain.getName()); + + if (!domain.getSegments().isEmpty()) { + for (Segment segment : domain.getSegments().values()) { + segment.accept(m_visitor); + } + } + + endTag(ENTITY_DOMAIN); + } + + @Override + public void visitError(Error error) { + startTag(ENTITY_ERROR, true, null, ATTR_ID, error.getId(), ATTR_COUNT, error.getCount()); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, true, null, ATTR_ID, machine.getId(), ATTR_COUNT, machine.getCount()); + } + + @Override + public void visitSegment(Segment segment) { + startTag(ENTITY_SEGMENT, null, ATTR_ID, segment.getId(), ATTR_ERROR, segment.getError(), ATTR_URL, segment.getUrl(), ATTR_URL_DURATION, toString(segment.getUrlDuration(), "0.00"), ATTR_SERVICE, segment.getService(), ATTR_SERVICE_DURATION, toString(segment.getServiceDuration(), "0.00"), ATTR_SQL, segment.getSql(), ATTR_SQL_DURATION, toString(segment.getSqlDuration(), "0.00"), ATTR_CALL, segment.getCall(), ATTR_CALL_DURATION, toString(segment.getCallDuration(), "0.00"), ATTR_CACHE, segment.getCache(), ATTR_CACHE_DURATION, toString(segment.getCacheDuration(), "0.00"), ATTR_URL_ERROR, segment.getUrlError(), ATTR_URL_SUM, toString(segment.getUrlSum(), "0.00"), ATTR_SERVICE_ERROR, segment.getServiceError(), ATTR_SERVICE_SUM, toString(segment.getServiceSum(), "0.00"), ATTR_SQL_ERROR, segment.getSqlError(), ATTR_SQL_SUM, toString(segment.getSqlSum(), "0.00"), ATTR_CALL_ERROR, segment.getCallError(), ATTR_CALL_SUM, toString(segment.getCallSum(), "0.00"), ATTR_CACHE_ERROR, segment.getCacheError(), ATTR_CACHE_SUM, toString(segment.getCacheSum(), "0.00")); + + if (!segment.getErrors().isEmpty()) { + for (Error error : segment.getErrors().values()) { + error.accept(m_visitor); + } + } + + if (!segment.getMachines().isEmpty()) { + for (Machine machine : segment.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_SEGMENT); + } + + @Override + public void visitTopReport(TopReport topReport) { + startTag(ENTITY_TOP_REPORT, null, ATTR_DOMAIN, topReport.getDomain(), ATTR_STARTTIME, toString(topReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(topReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!topReport.getDomains().isEmpty()) { + for (Domain domain : topReport.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_TOP_REPORT); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/ILinker.java new file mode 100644 index 0000000000..25c7832011 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/ILinker.java @@ -0,0 +1,18 @@ +package com.dianping.cat.consumer.top.model.transform; + +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public interface ILinker { + + public boolean onDomain(TopReport parent, Domain domain); + + public boolean onError(Segment parent, Error error); + + public boolean onMachine(Segment parent, Machine machine); + + public boolean onSegment(Domain parent, Segment segment); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IMaker.java new file mode 100644 index 0000000000..7622f02582 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IMaker.java @@ -0,0 +1,20 @@ +package com.dianping.cat.consumer.top.model.transform; + +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public interface IMaker { + + public Domain buildDomain(T node); + + public Error buildError(T node); + + public Machine buildMachine(T node); + + public Segment buildSegment(T node); + + public TopReport buildTopReport(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IParser.java new file mode 100644 index 0000000000..e6627cd697 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/top/model/transform/IParser.java @@ -0,0 +1,19 @@ +package com.dianping.cat.consumer.top.model.transform; + +import com.dianping.cat.consumer.top.model.entity.Domain; +import com.dianping.cat.consumer.top.model.entity.Error; +import com.dianping.cat.consumer.top.model.entity.Machine; +import com.dianping.cat.consumer.top.model.entity.Segment; +import com.dianping.cat.consumer.top.model.entity.TopReport; + +public interface IParser { + public TopReport parse(IMaker maker, ILinker linker, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); + + public void parseForError(IMaker maker, ILinker linker, Error parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForSegment(IMaker maker, ILinker linker, Segment parent, T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionAnalyzer.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionAnalyzer.java index ba474f77c0..4a8507ccf4 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionAnalyzer.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionAnalyzer.java @@ -24,17 +24,16 @@ import java.util.Map; import java.util.Set; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Threads; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import com.dianping.cat.support.Threads; +import jakarta.annotation.Resource; import com.dianping.cat.Cat; import com.dianping.cat.CatConstants; import com.dianping.cat.analysis.AbstractMessageAnalyzer; +import com.dianping.cat.analysis.ContainerMessageAnalyzerFactory; import com.dianping.cat.analysis.MessageAnalyzer; import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.config.server.ServerFilterConfigManager; import com.dianping.cat.config.transaction.TpValueStatisticConfigManager; import com.dianping.cat.consumer.transaction.model.entity.AllDuration; @@ -53,25 +52,28 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.ReportManager; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; -@Named(type = MessageAnalyzer.class, value = TransactionAnalyzer.ID, instantiationStrategy = Named.PER_LOOKUP) -public class TransactionAnalyzer extends AbstractMessageAnalyzer implements LogEnabled { +@Component(ContainerMessageAnalyzerFactory.ANALYZER_BEAN_PREFIX + TransactionAnalyzer.ID) +@Scope("prototype") +public class TransactionAnalyzer extends AbstractMessageAnalyzer { public static final String ID = "transaction"; private static final int m_statusCodeCountLimit = 100; - @Inject(ID) - private ReportManager m_reportManager; + @Resource(name = TransactionAnalyzer.ID + "ReportManager") + private ReportManager transactionReportManager; - @Inject - private ServerFilterConfigManager m_filterConfigManager; + @Resource(name = "serverFilterConfigManager") + private ServerFilterConfigManager serverFilterConfigManager; - @Inject - private TpValueStatisticConfigManager m_statisticManager; + @Resource(name = "tpValueStatisticConfigManager") + private TpValueStatisticConfigManager tpValueStatisticConfigManager; - @Inject - private AtomicMessageConfigManager m_atomicMessageConfigManager; + @Resource(name = "atomicMessageConfigManager") + private AtomicMessageConfigManager atomicMessageConfigManager; private final TransactionStatisticsComputer m_computer = new TransactionStatisticsComputer(); @@ -104,7 +106,7 @@ private void cleanUpReports() { Transaction t = Cat.newTransaction("CleanUpTransactionReports", minute); try { - Set domains = m_reportManager.getDomains(m_startTime); + Set domains = transactionReportManager.getDomains(m_startTime); m_computer.setMaxDurationMinute(m_serverConfigManager.getTpValueExpireMinute()); @@ -114,17 +116,17 @@ private void cleanUpReports() { tran.addData("domain", domain); TransactionReportCountFilter visitor = new TransactionReportCountFilter(m_serverConfigManager.getMaxTypeThreshold(), - m_atomicMessageConfigManager.getMaxNameThreshold(domain), m_serverConfigManager.getTypeNameLengthLimit()); + atomicMessageConfigManager.getMaxNameThreshold(domain), m_serverConfigManager.getTypeNameLengthLimit()); try { - TransactionReport transactionReport = m_reportManager.getHourlyReport(m_startTime, domain, false); + TransactionReport transactionReport = transactionReportManager.getHourlyReport(m_startTime, domain, false); m_computer.visitTransactionReport(transactionReport); visitor.visitTransactionReport(transactionReport); tran.success(); } catch (Exception e) { try { - TransactionReport transactionReport = m_reportManager.getHourlyReport(m_startTime, domain, false); + TransactionReport transactionReport = transactionReportManager.getHourlyReport(m_startTime, domain, false); m_computer.visitTransactionReport(transactionReport); visitor.visitTransactionReport(transactionReport); @@ -174,7 +176,7 @@ private DurationMeta computeBatchDuration(Transaction t, String[] tabs, Transact mergeMap(allTypeDurations, durations); mergeMap(allNameDurations, durations); - boolean statistic = m_statisticManager.shouldStatistic(t.getType(), domain); + boolean statistic = tpValueStatisticConfigManager.shouldStatistic(t.getType(), domain); if (statistic) { mergeMap(typeRange.getAllDurations(), durations); @@ -218,24 +220,19 @@ private int computeDuration(int duration) { @Override public synchronized void doCheckpoint(boolean atEnd) { if (atEnd && !isLocalMode()) { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); + transactionReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE_AND_DB, m_index); } else { - m_reportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + transactionReportManager.storeHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - private TransactionName findOrCreateName(TransactionType type, String name, String domain) { TransactionName transactionName = type.findName(name); if (transactionName == null) { int size = type.getNames().size(); - if (size > m_atomicMessageConfigManager.getMaxNameThreshold(domain)) { + if (size > atomicMessageConfigManager.getMaxNameThreshold(domain)) { transactionName = type.findOrCreateName(CatConstants.OTHERS); } else { transactionName = type.findOrCreateName(name); @@ -298,7 +295,7 @@ private String formatStatus(String status) { } public Set getDomains() { - return m_reportManager.getDomains(getStartTime()); + return transactionReportManager.getDomains(getStartTime()); } @Override @@ -322,7 +319,7 @@ public TransactionReport getReport(String domain) { @Override public ReportManager getReportManager() { - return m_reportManager; + return transactionReportManager; } @Override @@ -349,7 +346,7 @@ public boolean isEligable(MessageTree tree) { @Override protected void loadReports() { - m_reportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); + transactionReportManager.loadHourlyReports(getStartTime(), StoragePolicy.FILE, m_index); } private void mergeMap(Map allDurations, Map other) { @@ -384,7 +381,7 @@ private void parseDurations(DurationMeta meta, String duration) { @Override public void process(MessageTree tree) { String domain = tree.getDomain(); - TransactionReport report = m_reportManager.getHourlyReport(getStartTime(), domain, true); + TransactionReport report = transactionReportManager.getHourlyReport(getStartTime(), domain, true); List transactions = tree.findOrCreateTransactions(); for (Transaction t : transactions) { @@ -473,7 +470,7 @@ private void processTransaction(TransactionReport report, MessageTree tree, Tran String type = t.getType(); String name = t.getName(); - if (!m_filterConfigManager.discardTransaction(type, name)) { + if (!serverFilterConfigManager.discardTransaction(type, name)) { boolean valid = checkForTruncatedMessage(tree, t); if (valid) { @@ -563,7 +560,7 @@ private void processTypeAndName(Transaction t, TransactionType type, Transaction long current = t.getTimestamp() / 1000 / 60; int min = (int) (current % (60)); - boolean statistic = m_statisticManager.shouldStatistic(type.getId(), tree.getDomain()); + boolean statistic = tpValueStatisticConfigManager.shouldStatistic(type.getId(), tree.getDomain()); processNameGraph(t, name, min, duration, statistic, allDuration); processTypeRange(t, type, min, duration, statistic, allDuration); @@ -601,7 +598,7 @@ private TransactionReport queryReport(String domain) { long remainder = timestamp % ONE_HOUR; long current = timestamp - remainder; - TransactionReport report = m_reportManager.getHourlyReport(period, domain, false); + TransactionReport report = transactionReportManager.getHourlyReport(period, domain, false); m_computer.setMaxDurationMinute(m_serverConfigManager.getTpValueExpireMinute()); @@ -650,4 +647,25 @@ public double getMin() { } } + public void setAtomicMessageConfigManager(AtomicMessageConfigManager atomicMessageConfigManager) { + this.atomicMessageConfigManager = atomicMessageConfigManager; + } + + public void setServerFilterConfigManager(ServerFilterConfigManager serverFilterConfigManager) { + this.serverFilterConfigManager = serverFilterConfigManager; + } + + public void setTpValueStatisticConfigManager(TpValueStatisticConfigManager tpValueStatisticConfigManager) { + this.tpValueStatisticConfigManager = tpValueStatisticConfigManager; + } + + public void setTransactionReportManager(ReportManager transactionReportManager) { + this.transactionReportManager = transactionReportManager; + } + + @Resource(name = "serverConfigManager") + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + super.setServerConfigManager(serverConfigManager); + } + } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionDelegate.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionDelegate.java index 529bb8dfb7..d0eb682e17 100644 --- a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionDelegate.java +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/TransactionDelegate.java @@ -30,28 +30,20 @@ import com.dianping.cat.report.ReportDelegate; import com.dianping.cat.task.TaskManager; import com.dianping.cat.task.TaskManager.TaskProlicy; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import java.util.Date; import java.util.Map; -@Named(type = ReportDelegate.class, value = TransactionAnalyzer.ID) public class TransactionDelegate implements ReportDelegate { - @Inject private TaskManager m_taskManager; - @Inject private ServerFilterConfigManager m_configManager; - @Inject private AllReportConfigManager m_transactionManager; - @Inject private ServerConfigManager m_serverConfigManager; - @Inject private AtomicMessageConfigManager m_atomicMessageConfigManager; private TransactionStatisticsComputer m_computer = new TransactionStatisticsComputer(); @@ -124,4 +116,24 @@ public TransactionReport parseBinary(byte[] bytes) { public TransactionReport parseXml(String xml) throws Exception { return DefaultSaxParser.parse(xml); } + + public void setTaskManager(TaskManager taskManager) { + m_taskManager = taskManager; + } + + public void setConfigManager(ServerFilterConfigManager configManager) { + m_configManager = configManager; + } + + public void setTransactionManager(AllReportConfigManager transactionManager) { + m_transactionManager = transactionManager; + } + + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; + } + + public void setAtomicMessageConfigManager(AtomicMessageConfigManager atomicMessageConfigManager) { + m_atomicMessageConfigManager = atomicMessageConfigManager; + } } diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/BaseEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/BaseEntity.java new file mode 100644 index 0000000000..87fe391cb5 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.consumer.transaction.model; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.consumer.transaction.model.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/Constants.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/Constants.java new file mode 100644 index 0000000000..d4d10ef15d --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/Constants.java @@ -0,0 +1,110 @@ +package com.dianping.cat.consumer.transaction.model; + +public class Constants { + + public static final String ATTR_AVG = "avg"; + + public static final String ATTR_COUNT = "count"; + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_DURATION = "duration"; + + public static final String ATTR_ENDTIME = "endTime"; + + public static final String ATTR_FAILCOUNT = "failCount"; + + public static final String ATTR_FAILPERCENT = "failPercent"; + + public static final String ATTR_FAILS = "fails"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_IP = "ip"; + + public static final String ATTR_LINE50VALUE = "line50Value"; + + public static final String ATTR_LINE90VALUE = "line90Value"; + + public static final String ATTR_LINE95VALUE = "line95Value"; + + public static final String ATTR_LINE9999VALUE = "line9999Value"; + + public static final String ATTR_LINE999VALUE = "line999Value"; + + public static final String ATTR_LINE99VALUE = "line99Value"; + + public static final String ATTR_MAX = "max"; + + public static final String ATTR_MIN = "min"; + + public static final String ATTR_STARTTIME = "startTime"; + + public static final String ATTR_STD = "std"; + + public static final String ATTR_SUM = "sum"; + + public static final String ATTR_SUM2 = "sum2"; + + public static final String ATTR_TOTALCOUNT = "totalCount"; + + public static final String ATTR_TPS = "tps"; + + public static final String ATTR_VALUE = "value"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAIN_NAMES = "domain-names"; + + public static final String ELEMENT_FAILMESSAGEURL = "failMessageUrl"; + + public static final String ELEMENT_IP = "ip"; + + public static final String ELEMENT_IPS = "ips"; + + public static final String ELEMENT_LONGESTMESSAGEURL = "longestMessageUrl"; + + public static final String ELEMENT_SUCCESSMESSAGEURL = "successMessageUrl"; + + public static final String ENTITY_ALL_DURATION = "all-duration"; + + public static final String ENTITY_DURATION = "duration"; + + public static final String ENTITY_DURATIONS = "durations"; + + public static final String ENTITY_GRAPH = "graph"; + + public static final String ENTITY_GRAPHS = "graphs"; + + public static final String ENTITY_GRAPH_TREND = "graph-trend"; + + public static final String ENTITY_GRAPH2 = "graph2"; + + public static final String ENTITY_GRAPH2S = "graph2s"; + + public static final String ENTITY_MACHINE = "machine"; + + public static final String ENTITY_MACHINES = "machines"; + + public static final String ENTITY_NAME = "name"; + + public static final String ENTITY_NAMES = "names"; + + public static final String ENTITY_RANGE = "range"; + + public static final String ENTITY_RANGES = "ranges"; + + public static final String ENTITY_RANGE2 = "range2"; + + public static final String ENTITY_RANGE2S = "range2s"; + + public static final String ENTITY_STATUSCODE = "statusCode"; + + public static final String ENTITY_STATUSCODES = "statusCodes"; + + public static final String ENTITY_TRANSACTION_REPORT = "transaction-report"; + + public static final String ENTITY_TYPE = "type"; + + public static final String ENTITY_TYPES = "types"; +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IEntity.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IEntity.java new file mode 100644 index 0000000000..6d9f6b25f3 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.consumer.transaction.model; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IVisitor.java new file mode 100644 index 0000000000..af8df89f50 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/IVisitor.java @@ -0,0 +1,41 @@ +package com.dianping.cat.consumer.transaction.model; + +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public interface IVisitor { + + public void visitAllDuration(AllDuration allDuration); + + public void visitDuration(Duration duration); + + public void visitGraph(Graph graph); + + public void visitGraph2(Graph2 graph2); + + public void visitGraphTrend(GraphTrend graphTrend); + + public void visitMachine(Machine machine); + + public void visitName(TransactionName name); + + public void visitRange(Range range); + + public void visitRange2(Range2 range2); + + public void visitStatusCode(StatusCode statusCode); + + public void visitTransactionReport(TransactionReport transactionReport); + + public void visitType(TransactionType type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/AllDuration.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/AllDuration.java new file mode 100644 index 0000000000..193d6f9e39 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/AllDuration.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_ALL_DURATION; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class AllDuration extends BaseEntity { + private int m_value; + + private int m_count; + + public AllDuration() { + } + + public AllDuration(int value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAllDuration(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AllDuration) { + AllDuration _o = (AllDuration) obj; + + if (getValue() != _o.getValue()) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public int getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_value; + + return hash; + } + + public AllDuration incCount() { + m_count++; + return this; + } + + public AllDuration incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(AllDuration other) { + assertAttributeEquals(other, ENTITY_ALL_DURATION, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + } + + public AllDuration setCount(int count) { + m_count = count; + return this; + } + + public AllDuration setValue(int value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Duration.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Duration.java new file mode 100644 index 0000000000..8fd9c51333 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Duration.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_DURATION; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Duration extends BaseEntity { + private int m_value; + + private int m_count; + + public Duration() { + } + + public Duration(int value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDuration(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Duration) { + Duration _o = (Duration) obj; + + if (getValue() != _o.getValue()) { + return false; + } + + return true; + } + + return false; + } + + public int getCount() { + return m_count; + } + + public int getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_value; + + return hash; + } + + public Duration incCount() { + m_count++; + return this; + } + + public Duration incCount(int count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(Duration other) { + assertAttributeEquals(other, ENTITY_DURATION, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + } + + public Duration setCount(int count) { + m_count = count; + return this; + } + + public Duration setValue(int value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph.java new file mode 100644 index 0000000000..9c637f491e --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph.java @@ -0,0 +1,114 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Graph extends BaseEntity { + private int m_duration; + + private String m_sum = ""; + + private String m_avg = ""; + + private String m_count = ""; + + private String m_fails = ""; + + public Graph() { + } + + public Graph(int duration) { + m_duration = duration; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGraph(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Graph) { + Graph _o = (Graph) obj; + + if (getDuration() != _o.getDuration()) { + return false; + } + + return true; + } + + return false; + } + + public String getAvg() { + return m_avg; + } + + public String getCount() { + return m_count; + } + + public int getDuration() { + return m_duration; + } + + public String getFails() { + return m_fails; + } + + public String getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_duration; + + return hash; + } + + @Override + public void mergeAttributes(Graph other) { + assertAttributeEquals(other, ENTITY_GRAPH, ATTR_DURATION, m_duration, other.getDuration()); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + + m_count = other.getCount(); + + m_fails = other.getFails(); + } + + public Graph setAvg(String avg) { + m_avg = avg; + return this; + } + + public Graph setCount(String count) { + m_count = count; + return this; + } + + public Graph setDuration(int duration) { + m_duration = duration; + return this; + } + + public Graph setFails(String fails) { + m_fails = fails; + return this; + } + + public Graph setSum(String sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph2.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph2.java new file mode 100644 index 0000000000..22ef5a1c8f --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Graph2.java @@ -0,0 +1,114 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH2; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Graph2 extends BaseEntity { + private int m_duration; + + private String m_sum = ""; + + private String m_avg = ""; + + private String m_count = ""; + + private String m_fails = ""; + + public Graph2() { + } + + public Graph2(int duration) { + m_duration = duration; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGraph2(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Graph2) { + Graph2 _o = (Graph2) obj; + + if (getDuration() != _o.getDuration()) { + return false; + } + + return true; + } + + return false; + } + + public String getAvg() { + return m_avg; + } + + public String getCount() { + return m_count; + } + + public int getDuration() { + return m_duration; + } + + public String getFails() { + return m_fails; + } + + public String getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_duration; + + return hash; + } + + @Override + public void mergeAttributes(Graph2 other) { + assertAttributeEquals(other, ENTITY_GRAPH2, ATTR_DURATION, m_duration, other.getDuration()); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + + m_count = other.getCount(); + + m_fails = other.getFails(); + } + + public Graph2 setAvg(String avg) { + m_avg = avg; + return this; + } + + public Graph2 setCount(String count) { + m_count = count; + return this; + } + + public Graph2 setDuration(int duration) { + m_duration = duration; + return this; + } + + public Graph2 setFails(String fails) { + m_fails = fails; + return this; + } + + public Graph2 setSum(String sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/GraphTrend.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/GraphTrend.java new file mode 100644 index 0000000000..12076751c9 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/GraphTrend.java @@ -0,0 +1,114 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH_TREND; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class GraphTrend extends BaseEntity { + private int m_duration; + + private String m_sum = ""; + + private String m_avg = ""; + + private String m_count = ""; + + private String m_fails = ""; + + public GraphTrend() { + } + + public GraphTrend(int duration) { + m_duration = duration; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitGraphTrend(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof GraphTrend) { + GraphTrend _o = (GraphTrend) obj; + + if (getDuration() != _o.getDuration()) { + return false; + } + + return true; + } + + return false; + } + + public String getAvg() { + return m_avg; + } + + public String getCount() { + return m_count; + } + + public int getDuration() { + return m_duration; + } + + public String getFails() { + return m_fails; + } + + public String getSum() { + return m_sum; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_duration; + + return hash; + } + + @Override + public void mergeAttributes(GraphTrend other) { + assertAttributeEquals(other, ENTITY_GRAPH_TREND, ATTR_DURATION, m_duration, other.getDuration()); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + + m_count = other.getCount(); + + m_fails = other.getFails(); + } + + public GraphTrend setAvg(String avg) { + m_avg = avg; + return this; + } + + public GraphTrend setCount(String count) { + m_count = count; + return this; + } + + public GraphTrend setDuration(int duration) { + m_duration = duration; + return this; + } + + public GraphTrend setFails(String fails) { + m_fails = fails; + return this; + } + + public GraphTrend setSum(String sum) { + m_sum = sum; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Machine.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Machine.java new file mode 100644 index 0000000000..a62c0db08b --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Machine.java @@ -0,0 +1,102 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_MACHINE; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Machine extends BaseEntity { + private String m_ip; + + private Map m_types = new ConcurrentHashMap(); + + public Machine() { + } + + public Machine(String ip) { + m_ip = ip; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitMachine(this); + } + + public Machine addType(TransactionType type) { + m_types.put(type.getId(), type); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Machine) { + Machine _o = (Machine) obj; + + if (!equals(getIp(), _o.getIp())) { + return false; + } + + return true; + } + + return false; + } + + public TransactionType findType(String id) { + return m_types.get(id); + } + + public TransactionType findOrCreateType(String id) { + TransactionType type = m_types.get(id); + + if (type == null) { + synchronized (m_types) { + type = m_types.get(id); + + if (type == null) { + type = new TransactionType(id); + m_types.put(id, type); + } + } + } + + return type; + } + + public String getIp() { + return m_ip; + } + + public Map getTypes() { + return m_types; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_ip == null ? 0 : m_ip.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Machine other) { + assertAttributeEquals(other, ENTITY_MACHINE, ATTR_IP, m_ip, other.getIp()); + + } + + public TransactionType removeType(String id) { + return m_types.remove(id); + } + + public Machine setIp(String ip) { + m_ip = ip; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range.java new file mode 100644 index 0000000000..e53e8f0061 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range.java @@ -0,0 +1,294 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Range extends BaseEntity { + private int m_value; + + private int m_count; + + private double m_sum; + + private double m_avg; + + private int m_fails; + + private double m_min = 86400000d; + + private double m_max = -1d; + + private double m_line95Value; + + private double m_line99Value; + + private double m_line999Value; + + private double m_line90Value; + + private transient Map m_allDurations = new ConcurrentHashMap(); + + private transient boolean m_clearDuration; + + private double m_line50Value; + + private double m_line9999Value; + + public Range() { + } + + public Range(int value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRange(this); + } + + public Range addAllDuration(AllDuration allDuration) { + m_allDurations.put(allDuration.getValue(), allDuration); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Range) { + Range _o = (Range) obj; + + if (getValue() != _o.getValue()) { + return false; + } + + return true; + } + + return false; + } + + public AllDuration findAllDuration(int value) { + return m_allDurations.get(value); + } + + public AllDuration findOrCreateAllDuration(int value) { + AllDuration allDuration = m_allDurations.get(value); + + if (allDuration == null) { + synchronized (m_allDurations) { + allDuration = m_allDurations.get(value); + + if (allDuration == null) { + allDuration = new AllDuration(value); + m_allDurations.put(value, allDuration); + } + } + } + + return allDuration; + } + + public Map getAllDurations() { + return m_allDurations; + } + + public double getAvg() { + return m_avg; + } + + public boolean getClearDuration() { + return m_clearDuration; + } + + public int getCount() { + return m_count; + } + + public int getFails() { + return m_fails; + } + + public double getLine50Value() { + return m_line50Value; + } + + public double getLine90Value() { + return m_line90Value; + } + + public double getLine95Value() { + return m_line95Value; + } + + public double getLine9999Value() { + return m_line9999Value; + } + + public double getLine999Value() { + return m_line999Value; + } + + public double getLine99Value() { + return m_line99Value; + } + + public double getMax() { + return m_max; + } + + public double getMin() { + return m_min; + } + + public double getSum() { + return m_sum; + } + + public int getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_value; + + return hash; + } + + public Range incCount() { + m_count++; + return this; + } + + public Range incCount(int count) { + m_count += count; + return this; + } + + public Range incFails() { + m_fails++; + return this; + } + + public Range incFails(int fails) { + m_fails += fails; + return this; + } + + public boolean isClearDuration() { + return m_clearDuration; + } + + @Override + public void mergeAttributes(Range other) { + assertAttributeEquals(other, ENTITY_RANGE, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + + m_fails = other.getFails(); + + m_min = other.getMin(); + + m_max = other.getMax(); + + m_line95Value = other.getLine95Value(); + + m_line99Value = other.getLine99Value(); + + m_line999Value = other.getLine999Value(); + + m_line90Value = other.getLine90Value(); + + m_clearDuration = other.getClearDuration(); + + m_line50Value = other.getLine50Value(); + + m_line9999Value = other.getLine9999Value(); + } + + public AllDuration removeAllDuration(int value) { + return m_allDurations.remove(value); + } + + public Range setAvg(double avg) { + m_avg = avg; + return this; + } + + public Range setClearDuration(boolean clearDuration) { + m_clearDuration = clearDuration; + return this; + } + + public Range setCount(int count) { + m_count = count; + return this; + } + + public Range setFails(int fails) { + m_fails = fails; + return this; + } + + public Range setLine50Value(double line50Value) { + m_line50Value = line50Value; + return this; + } + + public Range setLine90Value(double line90Value) { + m_line90Value = line90Value; + return this; + } + + public Range setLine95Value(double line95Value) { + m_line95Value = line95Value; + return this; + } + + public Range setLine9999Value(double line9999Value) { + m_line9999Value = line9999Value; + return this; + } + + public Range setLine999Value(double line999Value) { + m_line999Value = line999Value; + return this; + } + + public Range setLine99Value(double line99Value) { + m_line99Value = line99Value; + return this; + } + + public Range setMax(double max) { + m_max = max; + return this; + } + + public Range setMin(double min) { + m_min = min; + return this; + } + + public Range setSum(double sum) { + m_sum = sum; + return this; + } + + public Range setValue(int value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range2.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range2.java new file mode 100644 index 0000000000..fc961db903 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/Range2.java @@ -0,0 +1,294 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE2; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class Range2 extends BaseEntity { + private int m_value; + + private int m_count; + + private double m_sum; + + private double m_avg; + + private int m_fails; + + private double m_min = 86400000d; + + private double m_max = -1d; + + private double m_line95Value; + + private double m_line99Value; + + private double m_line999Value; + + private double m_line90Value; + + private transient Map m_allDurations = new ConcurrentHashMap(); + + private transient boolean m_clearDuration; + + private double m_line50Value; + + private double m_line9999Value; + + public Range2() { + } + + public Range2(int value) { + m_value = value; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitRange2(this); + } + + public Range2 addAllDuration(AllDuration allDuration) { + m_allDurations.put(allDuration.getValue(), allDuration); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Range2) { + Range2 _o = (Range2) obj; + + if (getValue() != _o.getValue()) { + return false; + } + + return true; + } + + return false; + } + + public AllDuration findAllDuration(int value) { + return m_allDurations.get(value); + } + + public AllDuration findOrCreateAllDuration(int value) { + AllDuration allDuration = m_allDurations.get(value); + + if (allDuration == null) { + synchronized (m_allDurations) { + allDuration = m_allDurations.get(value); + + if (allDuration == null) { + allDuration = new AllDuration(value); + m_allDurations.put(value, allDuration); + } + } + } + + return allDuration; + } + + public Map getAllDurations() { + return m_allDurations; + } + + public double getAvg() { + return m_avg; + } + + public boolean getClearDuration() { + return m_clearDuration; + } + + public int getCount() { + return m_count; + } + + public int getFails() { + return m_fails; + } + + public double getLine50Value() { + return m_line50Value; + } + + public double getLine90Value() { + return m_line90Value; + } + + public double getLine95Value() { + return m_line95Value; + } + + public double getLine9999Value() { + return m_line9999Value; + } + + public double getLine999Value() { + return m_line999Value; + } + + public double getLine99Value() { + return m_line99Value; + } + + public double getMax() { + return m_max; + } + + public double getMin() { + return m_min; + } + + public double getSum() { + return m_sum; + } + + public int getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_value; + + return hash; + } + + public Range2 incCount() { + m_count++; + return this; + } + + public Range2 incCount(int count) { + m_count += count; + return this; + } + + public Range2 incFails() { + m_fails++; + return this; + } + + public Range2 incFails(int fails) { + m_fails += fails; + return this; + } + + public boolean isClearDuration() { + return m_clearDuration; + } + + @Override + public void mergeAttributes(Range2 other) { + assertAttributeEquals(other, ENTITY_RANGE2, ATTR_VALUE, m_value, other.getValue()); + + m_count = other.getCount(); + + m_sum = other.getSum(); + + m_avg = other.getAvg(); + + m_fails = other.getFails(); + + m_min = other.getMin(); + + m_max = other.getMax(); + + m_line95Value = other.getLine95Value(); + + m_line99Value = other.getLine99Value(); + + m_line999Value = other.getLine999Value(); + + m_line90Value = other.getLine90Value(); + + m_clearDuration = other.getClearDuration(); + + m_line50Value = other.getLine50Value(); + + m_line9999Value = other.getLine9999Value(); + } + + public AllDuration removeAllDuration(int value) { + return m_allDurations.remove(value); + } + + public Range2 setAvg(double avg) { + m_avg = avg; + return this; + } + + public Range2 setClearDuration(boolean clearDuration) { + m_clearDuration = clearDuration; + return this; + } + + public Range2 setCount(int count) { + m_count = count; + return this; + } + + public Range2 setFails(int fails) { + m_fails = fails; + return this; + } + + public Range2 setLine50Value(double line50Value) { + m_line50Value = line50Value; + return this; + } + + public Range2 setLine90Value(double line90Value) { + m_line90Value = line90Value; + return this; + } + + public Range2 setLine95Value(double line95Value) { + m_line95Value = line95Value; + return this; + } + + public Range2 setLine9999Value(double line9999Value) { + m_line9999Value = line9999Value; + return this; + } + + public Range2 setLine999Value(double line999Value) { + m_line999Value = line999Value; + return this; + } + + public Range2 setLine99Value(double line99Value) { + m_line99Value = line99Value; + return this; + } + + public Range2 setMax(double max) { + m_max = max; + return this; + } + + public Range2 setMin(double min) { + m_min = min; + return this; + } + + public Range2 setSum(double sum) { + m_sum = sum; + return this; + } + + public Range2 setValue(int value) { + m_value = value; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/StatusCode.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/StatusCode.java new file mode 100644 index 0000000000..3a2915b289 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/StatusCode.java @@ -0,0 +1,85 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_STATUSCODE; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class StatusCode extends BaseEntity { + private String m_id; + + private long m_count; + + public StatusCode() { + } + + public StatusCode(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitStatusCode(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StatusCode) { + StatusCode _o = (StatusCode) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public long getCount() { + return m_count; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public StatusCode incCount() { + m_count++; + return this; + } + + public StatusCode incCount(long count) { + m_count += count; + return this; + } + + @Override + public void mergeAttributes(StatusCode other) { + assertAttributeEquals(other, ENTITY_STATUSCODE, ATTR_ID, m_id, other.getId()); + + m_count = other.getCount(); + } + + public StatusCode setCount(long count) { + m_count = count; + return this; + } + + public StatusCode setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionName.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionName.java new file mode 100644 index 0000000000..82ef03f371 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionName.java @@ -0,0 +1,530 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_NAME; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class TransactionName extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private long m_failCount; + + private double m_failPercent; + + private double m_min = 86400000d; + + private double m_max = -1d; + + private double m_avg; + + private double m_sum; + + private double m_sum2; + + private double m_std; + + private String m_successMessageUrl; + + private String m_failMessageUrl; + + private Map m_ranges = new ConcurrentHashMap(); + + private Map m_durations = new ConcurrentHashMap(); + + private transient double m_totalPercent; + + private double m_tps; + + private double m_line95Value; + + private double m_line99Value; + + private double m_line999Value; + + private double m_line90Value; + + private Map m_graphs = new ConcurrentHashMap(); + + private transient Map m_allDurations = new ConcurrentHashMap(); + + private GraphTrend m_graphTrend; + + private Map m_statusCodes = new ConcurrentHashMap(); + + private double m_line50Value; + + private double m_line9999Value; + + private String m_longestMessageUrl; + + public TransactionName() { + } + + public TransactionName(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitName(this); + } + + public TransactionName addAllDuration(AllDuration allDuration) { + m_allDurations.put(allDuration.getValue(), allDuration); + return this; + } + + public TransactionName addDuration(Duration duration) { + m_durations.put(duration.getValue(), duration); + return this; + } + + public TransactionName addGraph(Graph graph) { + m_graphs.put(graph.getDuration(), graph); + return this; + } + + public TransactionName addRange(Range range) { + m_ranges.put(range.getValue(), range); + return this; + } + + public TransactionName addStatusCode(StatusCode statusCode) { + m_statusCodes.put(statusCode.getId(), statusCode); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TransactionName) { + TransactionName _o = (TransactionName) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public AllDuration findAllDuration(int value) { + return m_allDurations.get(value); + } + + public Duration findDuration(int value) { + return m_durations.get(value); + } + + public Graph findGraph(int duration) { + return m_graphs.get(duration); + } + + public Range findRange(int value) { + return m_ranges.get(value); + } + + public StatusCode findStatusCode(String id) { + return m_statusCodes.get(id); + } + + public AllDuration findOrCreateAllDuration(int value) { + AllDuration allDuration = m_allDurations.get(value); + + if (allDuration == null) { + synchronized (m_allDurations) { + allDuration = m_allDurations.get(value); + + if (allDuration == null) { + allDuration = new AllDuration(value); + m_allDurations.put(value, allDuration); + } + } + } + + return allDuration; + } + + public Duration findOrCreateDuration(int value) { + Duration duration = m_durations.get(value); + + if (duration == null) { + synchronized (m_durations) { + duration = m_durations.get(value); + + if (duration == null) { + duration = new Duration(value); + m_durations.put(value, duration); + } + } + } + + return duration; + } + + public Graph findOrCreateGraph(int duration) { + Graph graph = m_graphs.get(duration); + + if (graph == null) { + synchronized (m_graphs) { + graph = m_graphs.get(duration); + + if (graph == null) { + graph = new Graph(duration); + m_graphs.put(duration, graph); + } + } + } + + return graph; + } + + public Range findOrCreateRange(int value) { + Range range = m_ranges.get(value); + + if (range == null) { + synchronized (m_ranges) { + range = m_ranges.get(value); + + if (range == null) { + range = new Range(value); + m_ranges.put(value, range); + } + } + } + + return range; + } + + public StatusCode findOrCreateStatusCode(String id) { + StatusCode statusCode = m_statusCodes.get(id); + + if (statusCode == null) { + synchronized (m_statusCodes) { + statusCode = m_statusCodes.get(id); + + if (statusCode == null) { + statusCode = new StatusCode(id); + m_statusCodes.put(id, statusCode); + } + } + } + + return statusCode; + } + + public Map getAllDurations() { + return m_allDurations; + } + + public double getAvg() { + return m_avg; + } + + public Map getDurations() { + return m_durations; + } + + public long getFailCount() { + return m_failCount; + } + + public String getFailMessageUrl() { + return m_failMessageUrl; + } + + public double getFailPercent() { + return m_failPercent; + } + + public Map getGraphs() { + return m_graphs; + } + + public GraphTrend getGraphTrend() { + return m_graphTrend; + } + + public String getId() { + return m_id; + } + + public double getLine50Value() { + return m_line50Value; + } + + public double getLine90Value() { + return m_line90Value; + } + + public double getLine95Value() { + return m_line95Value; + } + + public double getLine9999Value() { + return m_line9999Value; + } + + public double getLine999Value() { + return m_line999Value; + } + + public double getLine99Value() { + return m_line99Value; + } + + public String getLongestMessageUrl() { + return m_longestMessageUrl; + } + + public double getMax() { + return m_max; + } + + public double getMin() { + return m_min; + } + + public Map getRanges() { + return m_ranges; + } + + public Map getStatusCodes() { + return m_statusCodes; + } + + public double getStd() { + return m_std; + } + + public String getSuccessMessageUrl() { + return m_successMessageUrl; + } + + public double getSum() { + return m_sum; + } + + public double getSum2() { + return m_sum2; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTotalPercent() { + return m_totalPercent; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public TransactionName incFailCount() { + m_failCount++; + return this; + } + + public TransactionName incFailCount(long failCount) { + m_failCount += failCount; + return this; + } + + public TransactionName incTotalCount() { + m_totalCount++; + return this; + } + + public TransactionName incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(TransactionName other) { + assertAttributeEquals(other, ENTITY_NAME, ATTR_ID, m_id, other.getId()); + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_min = other.getMin(); + + m_max = other.getMax(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_sum2 = other.getSum2(); + + m_std = other.getStd(); + + m_totalPercent = other.getTotalPercent(); + + m_tps = other.getTps(); + + m_line95Value = other.getLine95Value(); + + m_line99Value = other.getLine99Value(); + + m_line999Value = other.getLine999Value(); + + m_line90Value = other.getLine90Value(); + + m_line50Value = other.getLine50Value(); + + m_line9999Value = other.getLine9999Value(); + } + + public AllDuration removeAllDuration(int value) { + return m_allDurations.remove(value); + } + + public Duration removeDuration(int value) { + return m_durations.remove(value); + } + + public Graph removeGraph(int duration) { + return m_graphs.remove(duration); + } + + public Range removeRange(int value) { + return m_ranges.remove(value); + } + + public StatusCode removeStatusCode(String id) { + return m_statusCodes.remove(id); + } + + public TransactionName setAvg(double avg) { + m_avg = avg; + return this; + } + + public TransactionName setFailCount(long failCount) { + m_failCount = failCount; + return this; + } + + public TransactionName setFailMessageUrl(String failMessageUrl) { + m_failMessageUrl = failMessageUrl; + return this; + } + + public TransactionName setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public TransactionName setGraphTrend(GraphTrend graphTrend) { + m_graphTrend = graphTrend; + return this; + } + + public TransactionName setId(String id) { + m_id = id; + return this; + } + + public TransactionName setLine50Value(double line50Value) { + m_line50Value = line50Value; + return this; + } + + public TransactionName setLine90Value(double line90Value) { + m_line90Value = line90Value; + return this; + } + + public TransactionName setLine95Value(double line95Value) { + m_line95Value = line95Value; + return this; + } + + public TransactionName setLine9999Value(double line9999Value) { + m_line9999Value = line9999Value; + return this; + } + + public TransactionName setLine999Value(double line999Value) { + m_line999Value = line999Value; + return this; + } + + public TransactionName setLine99Value(double line99Value) { + m_line99Value = line99Value; + return this; + } + + public TransactionName setLongestMessageUrl(String longestMessageUrl) { + m_longestMessageUrl = longestMessageUrl; + return this; + } + + public TransactionName setMax(double max) { + m_max = max; + return this; + } + + public TransactionName setMin(double min) { + m_min = min; + return this; + } + + public TransactionName setStd(double std) { + m_std = std; + return this; + } + + public TransactionName setSuccessMessageUrl(String successMessageUrl) { + m_successMessageUrl = successMessageUrl; + return this; + } + + public TransactionName setSum(double sum) { + m_sum = sum; + return this; + } + + public TransactionName setSum2(double sum2) { + m_sum2 = sum2; + return this; + } + + public TransactionName setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public TransactionName setTotalPercent(double totalPercent) { + m_totalPercent = totalPercent; + return this; + } + + public TransactionName setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionReport.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionReport.java new file mode 100644 index 0000000000..2157aae3ed --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionReport.java @@ -0,0 +1,155 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TRANSACTION_REPORT; + +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class TransactionReport extends BaseEntity { + private String m_domain; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private Set m_domainNames = new LinkedHashSet(); + + private Map m_machines = new ConcurrentHashMap(); + + private Set m_ips = new LinkedHashSet(); + + public TransactionReport() { + } + + public TransactionReport(String domain) { + m_domain = domain; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitTransactionReport(this); + } + + public TransactionReport addDomain(String domain) { + m_domainNames.add(domain); + return this; + } + + public TransactionReport addIp(String ip) { + m_ips.add(ip); + return this; + } + + public TransactionReport addMachine(Machine machine) { + m_machines.put(machine.getIp(), machine); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TransactionReport) { + TransactionReport _o = (TransactionReport) obj; + + if (!equals(getDomain(), _o.getDomain())) { + return false; + } + + return true; + } + + return false; + } + + public Machine findMachine(String ip) { + return m_machines.get(ip); + } + + public Machine findOrCreateMachine(String ip) { + Machine machine = m_machines.get(ip); + + if (machine == null) { + synchronized (m_machines) { + machine = m_machines.get(ip); + + if (machine == null) { + machine = new Machine(ip); + m_machines.put(ip, machine); + } + } + } + + return machine; + } + + public String getDomain() { + return m_domain; + } + + public Set getDomainNames() { + return m_domainNames; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public Set getIps() { + return m_ips; + } + + public Map getMachines() { + return m_machines; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domain == null ? 0 : m_domain.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(TransactionReport other) { + assertAttributeEquals(other, ENTITY_TRANSACTION_REPORT, ATTR_DOMAIN, m_domain, other.getDomain()); + + if (other.getStartTime() != null) { + m_startTime = other.getStartTime(); + } + + if (other.getEndTime() != null) { + m_endTime = other.getEndTime(); + } + } + + public Machine removeMachine(String ip) { + return m_machines.remove(ip); + } + + public TransactionReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public TransactionReport setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public TransactionReport setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionType.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionType.java new file mode 100644 index 0000000000..18a227e3db --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/entity/TransactionType.java @@ -0,0 +1,500 @@ +package com.dianping.cat.consumer.transaction.model.entity; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TYPE; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.dianping.cat.consumer.transaction.model.BaseEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; + +public class TransactionType extends BaseEntity { + private String m_id; + + private long m_totalCount; + + private long m_failCount; + + private double m_failPercent; + + private double m_min = 86400000d; + + private double m_max = -1d; + + private double m_avg; + + private double m_sum; + + private double m_sum2; + + private double m_std; + + private String m_successMessageUrl; + + private String m_failMessageUrl; + + private Map m_names = new ConcurrentHashMap(); + + private double m_tps; + + private double m_line95Value; + + private double m_line99Value; + + private double m_line999Value; + + private double m_line90Value; + + private Map m_graph2s = new ConcurrentHashMap(); + + private transient Map m_allDurations = new ConcurrentHashMap(); + + private GraphTrend m_graphTrend; + + private Map m_range2s = new ConcurrentHashMap(); + + private double m_line50Value; + + private double m_line9999Value; + + private String m_longestMessageUrl; + + private Map m_dynamicAttributes = new LinkedHashMap(); + + public TransactionType() { + } + + public TransactionType(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitType(this); + } + + public TransactionType addAllDuration(AllDuration allDuration) { + m_allDurations.put(allDuration.getValue(), allDuration); + return this; + } + + public TransactionType addGraph2(Graph2 graph2) { + m_graph2s.put(graph2.getDuration(), graph2); + return this; + } + + public TransactionType addName(TransactionName name) { + m_names.put(name.getId(), name); + return this; + } + + public TransactionType addRange2(Range2 range2) { + m_range2s.put(range2.getValue(), range2); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TransactionType) { + TransactionType _o = (TransactionType) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public AllDuration findAllDuration(int value) { + return m_allDurations.get(value); + } + + public Graph2 findGraph2(int duration) { + return m_graph2s.get(duration); + } + + public TransactionName findName(String id) { + return m_names.get(id); + } + + public Range2 findRange2(int value) { + return m_range2s.get(value); + } + + public AllDuration findOrCreateAllDuration(int value) { + AllDuration allDuration = m_allDurations.get(value); + + if (allDuration == null) { + synchronized (m_allDurations) { + allDuration = m_allDurations.get(value); + + if (allDuration == null) { + allDuration = new AllDuration(value); + m_allDurations.put(value, allDuration); + } + } + } + + return allDuration; + } + + public Graph2 findOrCreateGraph2(int duration) { + Graph2 graph2 = m_graph2s.get(duration); + + if (graph2 == null) { + synchronized (m_graph2s) { + graph2 = m_graph2s.get(duration); + + if (graph2 == null) { + graph2 = new Graph2(duration); + m_graph2s.put(duration, graph2); + } + } + } + + return graph2; + } + + public TransactionName findOrCreateName(String id) { + TransactionName name = m_names.get(id); + + if (name == null) { + synchronized (m_names) { + name = m_names.get(id); + + if (name == null) { + name = new TransactionName(id); + m_names.put(id, name); + } + } + } + + return name; + } + + public Range2 findOrCreateRange2(int value) { + Range2 range2 = m_range2s.get(value); + + if (range2 == null) { + synchronized (m_range2s) { + range2 = m_range2s.get(value); + + if (range2 == null) { + range2 = new Range2(value); + m_range2s.put(value, range2); + } + } + } + + return range2; + } + + public String getDynamicAttribute(String name) { + return m_dynamicAttributes.get(name); + } + + public Map getDynamicAttributes() { + return m_dynamicAttributes; + } + + public Map getAllDurations() { + return m_allDurations; + } + + public double getAvg() { + return m_avg; + } + + public long getFailCount() { + return m_failCount; + } + + public String getFailMessageUrl() { + return m_failMessageUrl; + } + + public double getFailPercent() { + return m_failPercent; + } + + public Map getGraph2s() { + return m_graph2s; + } + + public GraphTrend getGraphTrend() { + return m_graphTrend; + } + + public String getId() { + return m_id; + } + + public double getLine50Value() { + return m_line50Value; + } + + public double getLine90Value() { + return m_line90Value; + } + + public double getLine95Value() { + return m_line95Value; + } + + public double getLine9999Value() { + return m_line9999Value; + } + + public double getLine999Value() { + return m_line999Value; + } + + public double getLine99Value() { + return m_line99Value; + } + + public String getLongestMessageUrl() { + return m_longestMessageUrl; + } + + public double getMax() { + return m_max; + } + + public double getMin() { + return m_min; + } + + public Map getNames() { + return m_names; + } + + public Map getRange2s() { + return m_range2s; + } + + public double getStd() { + return m_std; + } + + public String getSuccessMessageUrl() { + return m_successMessageUrl; + } + + public double getSum() { + return m_sum; + } + + public double getSum2() { + return m_sum2; + } + + public long getTotalCount() { + return m_totalCount; + } + + public double getTps() { + return m_tps; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public TransactionType incFailCount() { + m_failCount++; + return this; + } + + public TransactionType incFailCount(long failCount) { + m_failCount += failCount; + return this; + } + + public TransactionType incTotalCount() { + m_totalCount++; + return this; + } + + public TransactionType incTotalCount(long totalCount) { + m_totalCount += totalCount; + return this; + } + + @Override + public void mergeAttributes(TransactionType other) { + assertAttributeEquals(other, ENTITY_TYPE, ATTR_ID, m_id, other.getId()); + + for (Map.Entry e : other.getDynamicAttributes().entrySet()) { + m_dynamicAttributes.put(e.getKey(), e.getValue()); + } + + m_totalCount = other.getTotalCount(); + + m_failCount = other.getFailCount(); + + m_failPercent = other.getFailPercent(); + + m_min = other.getMin(); + + m_max = other.getMax(); + + m_avg = other.getAvg(); + + m_sum = other.getSum(); + + m_sum2 = other.getSum2(); + + m_std = other.getStd(); + + m_tps = other.getTps(); + + m_line95Value = other.getLine95Value(); + + m_line99Value = other.getLine99Value(); + + m_line999Value = other.getLine999Value(); + + m_line90Value = other.getLine90Value(); + + m_line50Value = other.getLine50Value(); + + m_line9999Value = other.getLine9999Value(); + } + + public AllDuration removeAllDuration(int value) { + return m_allDurations.remove(value); + } + + public Graph2 removeGraph2(int duration) { + return m_graph2s.remove(duration); + } + + public TransactionName removeName(String id) { + return m_names.remove(id); + } + + public Range2 removeRange2(int value) { + return m_range2s.remove(value); + } + + public void setDynamicAttribute(String name, String value) { + m_dynamicAttributes.put(name, value); + } + + public TransactionType setAvg(double avg) { + m_avg = avg; + return this; + } + + public TransactionType setFailCount(long failCount) { + m_failCount = failCount; + return this; + } + + public TransactionType setFailMessageUrl(String failMessageUrl) { + m_failMessageUrl = failMessageUrl; + return this; + } + + public TransactionType setFailPercent(double failPercent) { + m_failPercent = failPercent; + return this; + } + + public TransactionType setGraphTrend(GraphTrend graphTrend) { + m_graphTrend = graphTrend; + return this; + } + + public TransactionType setId(String id) { + m_id = id; + return this; + } + + public TransactionType setLine50Value(double line50Value) { + m_line50Value = line50Value; + return this; + } + + public TransactionType setLine90Value(double line90Value) { + m_line90Value = line90Value; + return this; + } + + public TransactionType setLine95Value(double line95Value) { + m_line95Value = line95Value; + return this; + } + + public TransactionType setLine9999Value(double line9999Value) { + m_line9999Value = line9999Value; + return this; + } + + public TransactionType setLine999Value(double line999Value) { + m_line999Value = line999Value; + return this; + } + + public TransactionType setLine99Value(double line99Value) { + m_line99Value = line99Value; + return this; + } + + public TransactionType setLongestMessageUrl(String longestMessageUrl) { + m_longestMessageUrl = longestMessageUrl; + return this; + } + + public TransactionType setMax(double max) { + m_max = max; + return this; + } + + public TransactionType setMin(double min) { + m_min = min; + return this; + } + + public TransactionType setStd(double std) { + m_std = std; + return this; + } + + public TransactionType setSuccessMessageUrl(String successMessageUrl) { + m_successMessageUrl = successMessageUrl; + return this; + } + + public TransactionType setSum(double sum) { + m_sum = sum; + return this; + } + + public TransactionType setSum2(double sum2) { + m_sum2 = sum2; + return this; + } + + public TransactionType setTotalCount(long totalCount) { + m_totalCount = totalCount; + return this; + } + + public TransactionType setTps(double tps) { + m_tps = tps; + return this; + } + +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/BaseVisitor.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/BaseVisitor.java new file mode 100644 index 0000000000..833a74f627 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/BaseVisitor.java @@ -0,0 +1,119 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import com.dianping.cat.consumer.transaction.model.IVisitor; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitAllDuration(AllDuration allDuration) { + } + + @Override + public void visitDuration(Duration duration) { + } + + @Override + public void visitGraph(Graph graph) { + } + + @Override + public void visitGraph2(Graph2 graph2) { + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + } + + @Override + public void visitMachine(Machine machine) { + for (TransactionType type : machine.getTypes().values()) { + visitType(type); + } + } + + @Override + public void visitName(TransactionName name) { + for (Range range : name.getRanges().values()) { + visitRange(range); + } + + for (Duration duration : name.getDurations().values()) { + visitDuration(duration); + } + + for (Graph graph : name.getGraphs().values()) { + visitGraph(graph); + } + + for (AllDuration allDuration : name.getAllDurations().values()) { + visitAllDuration(allDuration); + } + + if (name.getGraphTrend() != null) { + visitGraphTrend(name.getGraphTrend()); + } + + for (StatusCode statusCode : name.getStatusCodes().values()) { + visitStatusCode(statusCode); + } + } + + @Override + public void visitRange(Range range) { + for (AllDuration allDuration : range.getAllDurations().values()) { + visitAllDuration(allDuration); + } + } + + @Override + public void visitRange2(Range2 range2) { + for (AllDuration allDuration : range2.getAllDurations().values()) { + visitAllDuration(allDuration); + } + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + } + + @Override + public void visitTransactionReport(TransactionReport transactionReport) { + for (Machine machine : transactionReport.getMachines().values()) { + visitMachine(machine); + } + } + + @Override + public void visitType(TransactionType type) { + for (TransactionName name : type.getNames().values()) { + visitName(name); + } + + for (Graph2 graph2 : type.getGraph2s().values()) { + visitGraph2(graph2); + } + + for (AllDuration allDuration : type.getAllDurations().values()) { + visitAllDuration(allDuration); + } + + if (type.getGraphTrend() != null) { + visitGraphTrend(type.getGraphTrend()); + } + + for (Range2 range2 : type.getRange2s().values()) { + visitRange2(range2); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultLinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultLinker.java new file mode 100644 index 0000000000..85fb209d58 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultLinker.java @@ -0,0 +1,252 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onAllDuration(final TransactionType parent, final AllDuration allDuration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addAllDuration(allDuration); + } + }); + } else { + parent.addAllDuration(allDuration); + } + + return true; + } + + @Override + public boolean onAllDuration(final TransactionName parent, final AllDuration allDuration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addAllDuration(allDuration); + } + }); + } else { + parent.addAllDuration(allDuration); + } + + return true; + } + + @Override + public boolean onAllDuration(final Range parent, final AllDuration allDuration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addAllDuration(allDuration); + } + }); + } else { + parent.addAllDuration(allDuration); + } + + return true; + } + + @Override + public boolean onAllDuration(final Range2 parent, final AllDuration allDuration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addAllDuration(allDuration); + } + }); + } else { + parent.addAllDuration(allDuration); + } + + return true; + } + + @Override + public boolean onDuration(final TransactionName parent, final Duration duration) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDuration(duration); + } + }); + } else { + parent.addDuration(duration); + } + + return true; + } + + @Override + public boolean onGraph(final TransactionName parent, final Graph graph) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addGraph(graph); + } + }); + } else { + parent.addGraph(graph); + } + + return true; + } + + @Override + public boolean onGraph2(final TransactionType parent, final Graph2 graph2) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addGraph2(graph2); + } + }); + } else { + parent.addGraph2(graph2); + } + + return true; + } + + @Override + public boolean onGraphTrend(final TransactionType parent, final GraphTrend graphTrend) { + parent.setGraphTrend(graphTrend); + return true; + } + + @Override + public boolean onGraphTrend(final TransactionName parent, final GraphTrend graphTrend) { + parent.setGraphTrend(graphTrend); + return true; + } + + @Override + public boolean onMachine(final TransactionReport parent, final Machine machine) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addMachine(machine); + } + }); + } else { + parent.addMachine(machine); + } + + return true; + } + + @Override + public boolean onName(final TransactionType parent, final TransactionName name) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addName(name); + } + }); + } else { + parent.addName(name); + } + + return true; + } + + @Override + public boolean onRange(final TransactionName parent, final Range range) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRange(range); + } + }); + } else { + parent.addRange(range); + } + + return true; + } + + @Override + public boolean onRange2(final TransactionType parent, final Range2 range2) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addRange2(range2); + } + }); + } else { + parent.addRange2(range2); + } + + return true; + } + + @Override + public boolean onStatusCode(final TransactionName parent, final StatusCode statusCode) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addStatusCode(statusCode); + } + }); + } else { + parent.addStatusCode(statusCode); + } + + return true; + } + + @Override + public boolean onType(final Machine parent, final TransactionType type) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addType(type); + } + }); + } else { + parent.addType(type); + } + + return true; + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultMerger.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultMerger.java new file mode 100644 index 0000000000..2d98432b41 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultMerger.java @@ -0,0 +1,428 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import java.util.Stack; + +import com.dianping.cat.consumer.transaction.model.IEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private TransactionReport m_transactionReport; + + public DefaultMerger() { + } + + public DefaultMerger(TransactionReport transactionReport) { + m_transactionReport = transactionReport; + m_objs.push(transactionReport); + } + + public TransactionReport getTransactionReport() { + return m_transactionReport; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeAllDuration(AllDuration to, AllDuration from) { + to.mergeAttributes(from); + } + + protected void mergeDuration(Duration to, Duration from) { + to.mergeAttributes(from); + } + + protected void mergeGraph(Graph to, Graph from) { + to.mergeAttributes(from); + } + + protected void mergeGraph2(Graph2 to, Graph2 from) { + to.mergeAttributes(from); + } + + protected void mergeGraphTrend(GraphTrend to, GraphTrend from) { + to.mergeAttributes(from); + } + + protected void mergeMachine(Machine to, Machine from) { + to.mergeAttributes(from); + } + + protected void mergeName(TransactionName to, TransactionName from) { + to.mergeAttributes(from); + to.setSuccessMessageUrl(from.getSuccessMessageUrl()); + to.setFailMessageUrl(from.getFailMessageUrl()); + to.setLongestMessageUrl(from.getLongestMessageUrl()); + } + + protected void mergeRange(Range to, Range from) { + to.mergeAttributes(from); + } + + protected void mergeRange2(Range2 to, Range2 from) { + to.mergeAttributes(from); + } + + protected void mergeStatusCode(StatusCode to, StatusCode from) { + to.mergeAttributes(from); + } + + protected void mergeTransactionReport(TransactionReport to, TransactionReport from) { + to.mergeAttributes(from); + to.getDomainNames().addAll(from.getDomainNames()); + to.getIps().addAll(from.getIps()); + } + + protected void mergeType(TransactionType to, TransactionType from) { + to.mergeAttributes(from); + to.setSuccessMessageUrl(from.getSuccessMessageUrl()); + to.setFailMessageUrl(from.getFailMessageUrl()); + to.setLongestMessageUrl(from.getLongestMessageUrl()); + } + + @Override + public void visitAllDuration(AllDuration from) { + AllDuration to = (AllDuration) m_objs.peek(); + + mergeAllDuration(to, from); + visitAllDurationChildren(to, from); + } + + protected void visitAllDurationChildren(AllDuration to, AllDuration from) { + } + + @Override + public void visitDuration(Duration from) { + Duration to = (Duration) m_objs.peek(); + + mergeDuration(to, from); + visitDurationChildren(to, from); + } + + protected void visitDurationChildren(Duration to, Duration from) { + } + + @Override + public void visitGraph(Graph from) { + Graph to = (Graph) m_objs.peek(); + + mergeGraph(to, from); + visitGraphChildren(to, from); + } + + protected void visitGraphChildren(Graph to, Graph from) { + } + + @Override + public void visitGraph2(Graph2 from) { + Graph2 to = (Graph2) m_objs.peek(); + + mergeGraph2(to, from); + visitGraph2Children(to, from); + } + + protected void visitGraph2Children(Graph2 to, Graph2 from) { + } + + @Override + public void visitGraphTrend(GraphTrend from) { + GraphTrend to = (GraphTrend) m_objs.peek(); + + mergeGraphTrend(to, from); + visitGraphTrendChildren(to, from); + } + + protected void visitGraphTrendChildren(GraphTrend to, GraphTrend from) { + } + + @Override + public void visitMachine(Machine from) { + Machine to = (Machine) m_objs.peek(); + + mergeMachine(to, from); + visitMachineChildren(to, from); + } + + protected void visitMachineChildren(Machine to, Machine from) { + for (TransactionType source : from.getTypes().values()) { + TransactionType target = to.findType(source.getId()); + + if (target == null) { + target = new TransactionType(source.getId()); + to.addType(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitName(TransactionName from) { + TransactionName to = (TransactionName) m_objs.peek(); + + mergeName(to, from); + visitNameChildren(to, from); + } + + protected void visitNameChildren(TransactionName to, TransactionName from) { + for (Range source : from.getRanges().values()) { + Range target = to.findRange(source.getValue()); + + if (target == null) { + target = new Range(source.getValue()); + to.addRange(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Duration source : from.getDurations().values()) { + Duration target = to.findDuration(source.getValue()); + + if (target == null) { + target = new Duration(source.getValue()); + to.addDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Graph source : from.getGraphs().values()) { + Graph target = to.findGraph(source.getDuration()); + + if (target == null) { + target = new Graph(source.getDuration()); + to.addGraph(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (AllDuration source : from.getAllDurations().values()) { + AllDuration target = to.findAllDuration(source.getValue()); + + if (target == null) { + target = new AllDuration(source.getValue()); + to.addAllDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getGraphTrend() != null) { + GraphTrend target = to.getGraphTrend(); + + if (target == null) { + GraphTrend source = from.getGraphTrend(); + + target = new GraphTrend(source.getDuration()); + to.setGraphTrend(target); + } + + m_objs.push(target); + from.getGraphTrend().accept(this); + m_objs.pop(); + } + + for (StatusCode source : from.getStatusCodes().values()) { + StatusCode target = to.findStatusCode(source.getId()); + + if (target == null) { + target = new StatusCode(source.getId()); + to.addStatusCode(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitRange(Range from) { + Range to = (Range) m_objs.peek(); + + mergeRange(to, from); + visitRangeChildren(to, from); + } + + protected void visitRangeChildren(Range to, Range from) { + for (AllDuration source : from.getAllDurations().values()) { + AllDuration target = to.findAllDuration(source.getValue()); + + if (target == null) { + target = new AllDuration(source.getValue()); + to.addAllDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitRange2(Range2 from) { + Range2 to = (Range2) m_objs.peek(); + + mergeRange2(to, from); + visitRange2Children(to, from); + } + + protected void visitRange2Children(Range2 to, Range2 from) { + for (AllDuration source : from.getAllDurations().values()) { + AllDuration target = to.findAllDuration(source.getValue()); + + if (target == null) { + target = new AllDuration(source.getValue()); + to.addAllDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitStatusCode(StatusCode from) { + StatusCode to = (StatusCode) m_objs.peek(); + + mergeStatusCode(to, from); + visitStatusCodeChildren(to, from); + } + + protected void visitStatusCodeChildren(StatusCode to, StatusCode from) { + } + + @Override + public void visitTransactionReport(TransactionReport from) { + TransactionReport to = (TransactionReport) m_objs.peek(); + + mergeTransactionReport(to, from); + visitTransactionReportChildren(to, from); + } + + protected void visitTransactionReportChildren(TransactionReport to, TransactionReport from) { + for (Machine source : from.getMachines().values()) { + Machine target = to.findMachine(source.getIp()); + + if (target == null) { + target = new Machine(source.getIp()); + to.addMachine(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitType(TransactionType from) { + TransactionType to = (TransactionType) m_objs.peek(); + + mergeType(to, from); + visitTypeChildren(to, from); + } + + protected void visitTypeChildren(TransactionType to, TransactionType from) { + for (TransactionName source : from.getNames().values()) { + TransactionName target = to.findName(source.getId()); + + if (target == null) { + target = new TransactionName(source.getId()); + to.addName(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Graph2 source : from.getGraph2s().values()) { + Graph2 target = to.findGraph2(source.getDuration()); + + if (target == null) { + target = new Graph2(source.getDuration()); + to.addGraph2(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (AllDuration source : from.getAllDurations().values()) { + AllDuration target = to.findAllDuration(source.getValue()); + + if (target == null) { + target = new AllDuration(source.getValue()); + to.addAllDuration(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getGraphTrend() != null) { + GraphTrend target = to.getGraphTrend(); + + if (target == null) { + GraphTrend source = from.getGraphTrend(); + + target = new GraphTrend(source.getDuration()); + to.setGraphTrend(target); + } + + m_objs.push(target); + from.getGraphTrend().accept(this); + m_objs.pop(); + } + + for (Range2 source : from.getRange2s().values()) { + Range2 target = to.findRange2(source.getValue()); + + if (target == null) { + target = new Range2(source.getValue()); + to.addRange2(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..67fd774d37 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeBuilder.java @@ -0,0 +1,589 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.util.Map; + +import com.dianping.cat.consumer.transaction.model.IVisitor; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(TransactionReport transactionReport) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(transactionReport, out); + return out.toByteArray(); + } + + public static void build(TransactionReport transactionReport, OutputStream out) { + transactionReport.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitAllDuration(AllDuration allDuration) { + writeTag(1, 0); + writeInt(allDuration.getValue()); + + writeTag(2, 0); + writeInt(allDuration.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitDuration(Duration duration) { + writeTag(1, 0); + writeInt(duration.getValue()); + + writeTag(2, 0); + writeInt(duration.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitGraph(Graph graph) { + writeTag(1, 0); + writeInt(graph.getDuration()); + + writeTag(2, 0); + writeString(graph.getSum()); + + writeTag(3, 0); + writeString(graph.getAvg()); + + writeTag(4, 0); + writeString(graph.getCount()); + + writeTag(5, 0); + writeString(graph.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitGraph2(Graph2 graph2) { + writeTag(1, 0); + writeInt(graph2.getDuration()); + + writeTag(2, 0); + writeString(graph2.getSum()); + + writeTag(3, 0); + writeString(graph2.getAvg()); + + writeTag(4, 0); + writeString(graph2.getCount()); + + writeTag(5, 0); + writeString(graph2.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + writeTag(1, 0); + writeInt(graphTrend.getDuration()); + + writeTag(2, 0); + writeString(graphTrend.getSum()); + + writeTag(3, 0); + writeString(graphTrend.getAvg()); + + writeTag(4, 0); + writeString(graphTrend.getCount()); + + writeTag(5, 0); + writeString(graphTrend.getFails()); + + writeTag(63, 3); + } + + @Override + public void visitMachine(Machine machine) { + if (machine.getIp() != null) { + writeTag(1, 1); + writeString(machine.getIp()); + } + + if (!machine.getTypes().isEmpty()) { + writeTag(33, 2); + writeInt(machine.getTypes().size()); + + for (TransactionType type : machine.getTypes().values()) { + type.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitName(TransactionName name) { + if (name.getId() != null) { + writeTag(1, 1); + writeString(name.getId()); + } + + writeTag(2, 0); + writeLong(name.getTotalCount()); + + writeTag(3, 0); + writeLong(name.getFailCount()); + + writeTag(4, 0); + writeDouble(name.getFailPercent()); + + writeTag(5, 0); + writeDouble(name.getMin()); + + writeTag(6, 0); + writeDouble(name.getMax()); + + writeTag(7, 0); + writeDouble(name.getAvg()); + + writeTag(8, 0); + writeDouble(name.getSum()); + + writeTag(9, 0); + writeDouble(name.getSum2()); + + writeTag(10, 0); + writeDouble(name.getStd()); + + if (name.getSuccessMessageUrl() != null) { + writeTag(11, 1); + writeString(name.getSuccessMessageUrl()); + } + + if (name.getFailMessageUrl() != null) { + writeTag(12, 1); + writeString(name.getFailMessageUrl()); + } + + writeTag(13, 0); + writeDouble(name.getTps()); + + writeTag(14, 0); + writeDouble(name.getLine95Value()); + + writeTag(15, 0); + writeDouble(name.getLine99Value()); + + writeTag(16, 0); + writeDouble(name.getLine999Value()); + + writeTag(17, 0); + writeDouble(name.getLine90Value()); + + writeTag(18, 0); + writeDouble(name.getLine50Value()); + + writeTag(19, 0); + writeDouble(name.getLine9999Value()); + + if (name.getLongestMessageUrl() != null) { + writeTag(20, 1); + writeString(name.getLongestMessageUrl()); + } + + if (!name.getRanges().isEmpty()) { + writeTag(33, 2); + writeInt(name.getRanges().size()); + + for (Range range : name.getRanges().values()) { + range.accept(m_visitor); + } + } + + if (!name.getDurations().isEmpty()) { + writeTag(34, 2); + writeInt(name.getDurations().size()); + + for (Duration duration : name.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (!name.getGraphs().isEmpty()) { + writeTag(35, 2); + writeInt(name.getGraphs().size()); + + for (Graph graph : name.getGraphs().values()) { + graph.accept(m_visitor); + } + } + + if (name.getGraphTrend() != null) { + writeTag(36, 1); + name.getGraphTrend().accept(m_visitor); + } + + if (!name.getStatusCodes().isEmpty()) { + writeTag(37, 2); + writeInt(name.getStatusCodes().size()); + + for (StatusCode statusCode : name.getStatusCodes().values()) { + statusCode.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitRange(Range range) { + writeTag(1, 0); + writeInt(range.getValue()); + + writeTag(2, 0); + writeInt(range.getCount()); + + writeTag(3, 0); + writeDouble(range.getSum()); + + writeTag(4, 0); + writeDouble(range.getAvg()); + + writeTag(5, 0); + writeInt(range.getFails()); + + writeTag(6, 0); + writeDouble(range.getMin()); + + writeTag(7, 0); + writeDouble(range.getMax()); + + writeTag(8, 0); + writeDouble(range.getLine95Value()); + + writeTag(9, 0); + writeDouble(range.getLine99Value()); + + writeTag(10, 0); + writeDouble(range.getLine999Value()); + + writeTag(11, 0); + writeDouble(range.getLine90Value()); + + writeTag(12, 0); + writeDouble(range.getLine50Value()); + + writeTag(13, 0); + writeDouble(range.getLine9999Value()); + + writeTag(63, 3); + } + + @Override + public void visitRange2(Range2 range2) { + writeTag(1, 0); + writeInt(range2.getValue()); + + writeTag(2, 0); + writeInt(range2.getCount()); + + writeTag(3, 0); + writeDouble(range2.getSum()); + + writeTag(4, 0); + writeDouble(range2.getAvg()); + + writeTag(5, 0); + writeInt(range2.getFails()); + + writeTag(6, 0); + writeDouble(range2.getMin()); + + writeTag(7, 0); + writeDouble(range2.getMax()); + + writeTag(8, 0); + writeDouble(range2.getLine95Value()); + + writeTag(9, 0); + writeDouble(range2.getLine99Value()); + + writeTag(10, 0); + writeDouble(range2.getLine999Value()); + + writeTag(11, 0); + writeDouble(range2.getLine90Value()); + + writeTag(12, 0); + writeDouble(range2.getLine50Value()); + + writeTag(13, 0); + writeDouble(range2.getLine9999Value()); + + writeTag(63, 3); + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + if (statusCode.getId() != null) { + writeTag(1, 1); + writeString(statusCode.getId()); + } + + writeTag(2, 0); + writeLong(statusCode.getCount()); + + writeTag(63, 3); + } + + @Override + public void visitTransactionReport(TransactionReport transactionReport) { + writeTag(63, 0); + + if (transactionReport.getDomain() != null) { + writeTag(1, 1); + writeString(transactionReport.getDomain()); + } + + if (transactionReport.getStartTime() != null) { + writeTag(2, 1); + writeDate(transactionReport.getStartTime()); + } + + if (transactionReport.getEndTime() != null) { + writeTag(3, 1); + writeDate(transactionReport.getEndTime()); + } + + if (transactionReport.getDomainNames() != null) { + writeTag(4, 2); + writeInt(transactionReport.getDomainNames().size()); + + for (String domain : transactionReport.getDomainNames()) { + writeString(domain); + } + } + + if (transactionReport.getIps() != null) { + writeTag(5, 2); + writeInt(transactionReport.getIps().size()); + + for (String ip : transactionReport.getIps()) { + writeString(ip); + } + } + + if (!transactionReport.getMachines().isEmpty()) { + writeTag(33, 2); + writeInt(transactionReport.getMachines().size()); + + for (Machine machine : transactionReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + @Override + public void visitType(TransactionType type) { + if (type.getId() != null) { + writeTag(1, 1); + writeString(type.getId()); + } + + writeTag(2, 0); + writeLong(type.getTotalCount()); + + writeTag(3, 0); + writeLong(type.getFailCount()); + + writeTag(4, 0); + writeDouble(type.getFailPercent()); + + writeTag(5, 0); + writeDouble(type.getMin()); + + writeTag(6, 0); + writeDouble(type.getMax()); + + writeTag(7, 0); + writeDouble(type.getAvg()); + + writeTag(8, 0); + writeDouble(type.getSum()); + + writeTag(9, 0); + writeDouble(type.getSum2()); + + writeTag(10, 0); + writeDouble(type.getStd()); + + if (type.getSuccessMessageUrl() != null) { + writeTag(11, 1); + writeString(type.getSuccessMessageUrl()); + } + + if (type.getFailMessageUrl() != null) { + writeTag(12, 1); + writeString(type.getFailMessageUrl()); + } + + writeTag(13, 0); + writeDouble(type.getTps()); + + writeTag(14, 0); + writeDouble(type.getLine95Value()); + + writeTag(15, 0); + writeDouble(type.getLine99Value()); + + writeTag(16, 0); + writeDouble(type.getLine999Value()); + + writeTag(17, 0); + writeDouble(type.getLine90Value()); + + writeTag(18, 0); + writeDouble(type.getLine50Value()); + + writeTag(19, 0); + writeDouble(type.getLine9999Value()); + + if (type.getLongestMessageUrl() != null) { + writeTag(20, 1); + writeString(type.getLongestMessageUrl()); + } + + if (!type.getNames().isEmpty()) { + writeTag(33, 2); + writeInt(type.getNames().size()); + + for (TransactionName name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + if (!type.getGraph2s().isEmpty()) { + writeTag(34, 2); + writeInt(type.getGraph2s().size()); + + for (Graph2 graph2 : type.getGraph2s().values()) { + graph2.accept(m_visitor); + } + } + + if (type.getGraphTrend() != null) { + writeTag(35, 1); + type.getGraphTrend().accept(m_visitor); + } + + if (!type.getRange2s().isEmpty()) { + writeTag(36, 2); + writeInt(type.getRange2s().size()); + + for (Range2 range2 : type.getRange2s().values()) { + range2.accept(m_visitor); + } + } + + if (!type.getDynamicAttributes().isEmpty()) { + writeTag(63, 2); + writeInt(type.getDynamicAttributes().size()); + + for (Map.Entry dynamicAttribute : type.getDynamicAttributes().entrySet()) { + writeString(dynamicAttribute.getKey()); + writeString(dynamicAttribute.getValue()); + } + } + + writeTag(63, 3); + } + + private void writeDate(java.util.Date value) { + try { + writeVarint(value.getTime()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeDouble(double value) { + try { + writeVarint(Double.doubleToLongBits(value)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeLong(long value) { + try { + writeVarint(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..9e16888cff --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultNativeParser.java @@ -0,0 +1,739 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.util.Map; + +import com.dianping.cat.consumer.transaction.model.IVisitor; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static TransactionReport parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static TransactionReport parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + TransactionReport transactionReport = new TransactionReport(); + + try { + transactionReport.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return transactionReport; + } + + @Override + public void visitAllDuration(AllDuration allDuration) { + byte tag; + + while ((tag = readTag()) != -1) { + visitAllDurationChildren(allDuration, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitAllDurationChildren(AllDuration allDuration, int _field, int _type) { + switch (_field) { + case 1: + allDuration.setValue(readInt()); + break; + case 2: + allDuration.setCount(readInt()); + break; + } + } + + @Override + public void visitDuration(Duration duration) { + byte tag; + + while ((tag = readTag()) != -1) { + visitDurationChildren(duration, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitDurationChildren(Duration duration, int _field, int _type) { + switch (_field) { + case 1: + duration.setValue(readInt()); + break; + case 2: + duration.setCount(readInt()); + break; + } + } + + @Override + public void visitGraph(Graph graph) { + byte tag; + + while ((tag = readTag()) != -1) { + visitGraphChildren(graph, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitGraphChildren(Graph graph, int _field, int _type) { + switch (_field) { + case 1: + graph.setDuration(readInt()); + break; + case 2: + graph.setSum(readString()); + break; + case 3: + graph.setAvg(readString()); + break; + case 4: + graph.setCount(readString()); + break; + case 5: + graph.setFails(readString()); + break; + } + } + + @Override + public void visitGraph2(Graph2 graph2) { + byte tag; + + while ((tag = readTag()) != -1) { + visitGraph2Children(graph2, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitGraph2Children(Graph2 graph2, int _field, int _type) { + switch (_field) { + case 1: + graph2.setDuration(readInt()); + break; + case 2: + graph2.setSum(readString()); + break; + case 3: + graph2.setAvg(readString()); + break; + case 4: + graph2.setCount(readString()); + break; + case 5: + graph2.setFails(readString()); + break; + } + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + byte tag; + + while ((tag = readTag()) != -1) { + visitGraphTrendChildren(graphTrend, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitGraphTrendChildren(GraphTrend graphTrend, int _field, int _type) { + switch (_field) { + case 1: + graphTrend.setDuration(readInt()); + break; + case 2: + graphTrend.setSum(readString()); + break; + case 3: + graphTrend.setAvg(readString()); + break; + case 4: + graphTrend.setCount(readString()); + break; + case 5: + graphTrend.setFails(readString()); + break; + } + } + + @Override + public void visitMachine(Machine machine) { + byte tag; + + while ((tag = readTag()) != -1) { + visitMachineChildren(machine, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitMachineChildren(Machine machine, int _field, int _type) { + switch (_field) { + case 1: + machine.setIp(readString()); + break; + case 33: + if (_type == 1) { + TransactionType type = new TransactionType(); + + visitType(type); + m_linker.onType(machine, type); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + TransactionType type = new TransactionType(); + + visitType(type); + m_linker.onType(machine, type); + } + } + break; + } + } + + @Override + public void visitName(TransactionName name) { + byte tag; + + while ((tag = readTag()) != -1) { + visitNameChildren(name, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitNameChildren(TransactionName name, int _field, int _type) { + switch (_field) { + case 1: + name.setId(readString()); + break; + case 2: + name.setTotalCount(readLong()); + break; + case 3: + name.setFailCount(readLong()); + break; + case 4: + name.setFailPercent(readDouble()); + break; + case 5: + name.setMin(readDouble()); + break; + case 6: + name.setMax(readDouble()); + break; + case 7: + name.setAvg(readDouble()); + break; + case 8: + name.setSum(readDouble()); + break; + case 9: + name.setSum2(readDouble()); + break; + case 10: + name.setStd(readDouble()); + break; + case 11: + name.setSuccessMessageUrl(readString()); + break; + case 12: + name.setFailMessageUrl(readString()); + break; + case 13: + name.setTps(readDouble()); + break; + case 14: + name.setLine95Value(readDouble()); + break; + case 15: + name.setLine99Value(readDouble()); + break; + case 16: + name.setLine999Value(readDouble()); + break; + case 17: + name.setLine90Value(readDouble()); + break; + case 18: + name.setLine50Value(readDouble()); + break; + case 19: + name.setLine9999Value(readDouble()); + break; + case 20: + name.setLongestMessageUrl(readString()); + break; + case 33: + if (_type == 1) { + Range range = new Range(); + + visitRange(range); + m_linker.onRange(name, range); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Range range = new Range(); + + visitRange(range); + m_linker.onRange(name, range); + } + } + break; + case 34: + if (_type == 1) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(name, duration); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Duration duration = new Duration(); + + visitDuration(duration); + m_linker.onDuration(name, duration); + } + } + break; + case 35: + if (_type == 1) { + Graph graph = new Graph(); + + visitGraph(graph); + m_linker.onGraph(name, graph); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Graph graph = new Graph(); + + visitGraph(graph); + m_linker.onGraph(name, graph); + } + } + break; + case 36: + GraphTrend graphTrend = new GraphTrend(); + + visitGraphTrend(graphTrend); + m_linker.onGraphTrend(name, graphTrend); + break; + case 37: + if (_type == 1) { + StatusCode statusCode = new StatusCode(); + + visitStatusCode(statusCode); + m_linker.onStatusCode(name, statusCode); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + StatusCode statusCode = new StatusCode(); + + visitStatusCode(statusCode); + m_linker.onStatusCode(name, statusCode); + } + } + break; + } + } + + @Override + public void visitRange(Range range) { + byte tag; + + while ((tag = readTag()) != -1) { + visitRangeChildren(range, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitRangeChildren(Range range, int _field, int _type) { + switch (_field) { + case 1: + range.setValue(readInt()); + break; + case 2: + range.setCount(readInt()); + break; + case 3: + range.setSum(readDouble()); + break; + case 4: + range.setAvg(readDouble()); + break; + case 5: + range.setFails(readInt()); + break; + case 6: + range.setMin(readDouble()); + break; + case 7: + range.setMax(readDouble()); + break; + case 8: + range.setLine95Value(readDouble()); + break; + case 9: + range.setLine99Value(readDouble()); + break; + case 10: + range.setLine999Value(readDouble()); + break; + case 11: + range.setLine90Value(readDouble()); + break; + case 12: + range.setLine50Value(readDouble()); + break; + case 13: + range.setLine9999Value(readDouble()); + break; + } + } + + @Override + public void visitRange2(Range2 range2) { + byte tag; + + while ((tag = readTag()) != -1) { + visitRange2Children(range2, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitRange2Children(Range2 range2, int _field, int _type) { + switch (_field) { + case 1: + range2.setValue(readInt()); + break; + case 2: + range2.setCount(readInt()); + break; + case 3: + range2.setSum(readDouble()); + break; + case 4: + range2.setAvg(readDouble()); + break; + case 5: + range2.setFails(readInt()); + break; + case 6: + range2.setMin(readDouble()); + break; + case 7: + range2.setMax(readDouble()); + break; + case 8: + range2.setLine95Value(readDouble()); + break; + case 9: + range2.setLine99Value(readDouble()); + break; + case 10: + range2.setLine999Value(readDouble()); + break; + case 11: + range2.setLine90Value(readDouble()); + break; + case 12: + range2.setLine50Value(readDouble()); + break; + case 13: + range2.setLine9999Value(readDouble()); + break; + } + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + byte tag; + + while ((tag = readTag()) != -1) { + visitStatusCodeChildren(statusCode, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitStatusCodeChildren(StatusCode statusCode, int _field, int _type) { + switch (_field) { + case 1: + statusCode.setId(readString()); + break; + case 2: + statusCode.setCount(readLong()); + break; + } + } + + @Override + public void visitTransactionReport(TransactionReport transactionReport) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitTransactionReportChildren(transactionReport, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitTransactionReportChildren(TransactionReport transactionReport, int _field, int _type) { + switch (_field) { + case 1: + transactionReport.setDomain(readString()); + break; + case 2: + transactionReport.setStartTime(readDate()); + break; + case 3: + transactionReport.setEndTime(readDate()); + break; + case 4: + if (_type == 1) { + transactionReport.addDomain(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + transactionReport.addDomain(readString()); + } + } + break; + case 5: + if (_type == 1) { + transactionReport.addIp(readString()); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + transactionReport.addIp(readString()); + } + } + break; + case 33: + if (_type == 1) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(transactionReport, machine); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Machine machine = new Machine(); + + visitMachine(machine); + m_linker.onMachine(transactionReport, machine); + } + } + break; + } + } + + @Override + public void visitType(TransactionType type) { + byte tag; + + while ((tag = readTag()) != -1) { + visitTypeChildren(type, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitTypeChildren(TransactionType type, int _field, int _type) { + switch (_field) { + case 1: + type.setId(readString()); + break; + case 2: + type.setTotalCount(readLong()); + break; + case 3: + type.setFailCount(readLong()); + break; + case 4: + type.setFailPercent(readDouble()); + break; + case 5: + type.setMin(readDouble()); + break; + case 6: + type.setMax(readDouble()); + break; + case 7: + type.setAvg(readDouble()); + break; + case 8: + type.setSum(readDouble()); + break; + case 9: + type.setSum2(readDouble()); + break; + case 10: + type.setStd(readDouble()); + break; + case 11: + type.setSuccessMessageUrl(readString()); + break; + case 12: + type.setFailMessageUrl(readString()); + break; + case 13: + type.setTps(readDouble()); + break; + case 14: + type.setLine95Value(readDouble()); + break; + case 15: + type.setLine99Value(readDouble()); + break; + case 16: + type.setLine999Value(readDouble()); + break; + case 17: + type.setLine90Value(readDouble()); + break; + case 18: + type.setLine50Value(readDouble()); + break; + case 19: + type.setLine9999Value(readDouble()); + break; + case 20: + type.setLongestMessageUrl(readString()); + break; + case 33: + if (_type == 1) { + TransactionName name = new TransactionName(); + + visitName(name); + m_linker.onName(type, name); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + TransactionName name = new TransactionName(); + + visitName(name); + m_linker.onName(type, name); + } + } + break; + case 34: + if (_type == 1) { + Graph2 graph2 = new Graph2(); + + visitGraph2(graph2); + m_linker.onGraph2(type, graph2); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Graph2 graph2 = new Graph2(); + + visitGraph2(graph2); + m_linker.onGraph2(type, graph2); + } + } + break; + case 35: + GraphTrend graphTrend = new GraphTrend(); + + visitGraphTrend(graphTrend); + m_linker.onGraphTrend(type, graphTrend); + break; + case 36: + if (_type == 1) { + Range2 range2 = new Range2(); + + visitRange2(range2); + m_linker.onRange2(type, range2); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Range2 range2 = new Range2(); + + visitRange2(range2); + m_linker.onRange2(type, range2); + } + } + break; + case 63: + Map dynamicAttribute = type.getDynamicAttributes(); + + for (int i = readInt(); i > 0; i--) { + String key = readString(); + String value = readString(); + + dynamicAttribute.put(key, value); + } + break; + } + } + + private java.util.Date readDate() { + try { + return new java.util.Date(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private double readDouble() { + try { + return Double.longBitsToDouble(readVarint(64)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private long readLong() { + try { + return readVarint(64); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..78d65d8197 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxMaker.java @@ -0,0 +1,596 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE50VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE90VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE95VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE9999VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE999VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE99VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_MAX; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_MIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_STD; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_SUM2; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_TPS; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; + +import java.util.Map; +import org.xml.sax.Attributes; + +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AllDuration buildAllDuration(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + AllDuration allDuration = new AllDuration(value == null ? 0 : convert(Integer.class, value, 0)); + + if (count != null) { + allDuration.setCount(convert(Integer.class, count, 0)); + } + + return allDuration; + } + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Duration buildDuration(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + Duration duration = new Duration(value == null ? 0 : convert(Integer.class, value, 0)); + + if (count != null) { + duration.setCount(convert(Integer.class, count, 0)); + } + + return duration; + } + + @Override + public Graph buildGraph(Attributes attributes) { + String duration = attributes.getValue(ATTR_DURATION); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + String count = attributes.getValue(ATTR_COUNT); + String fails = attributes.getValue(ATTR_FAILS); + Graph graph = new Graph(duration == null ? 0 : convert(Integer.class, duration, 0)); + + if (sum != null) { + graph.setSum(sum); + } + + if (avg != null) { + graph.setAvg(avg); + } + + if (count != null) { + graph.setCount(count); + } + + if (fails != null) { + graph.setFails(fails); + } + + return graph; + } + + @Override + public Graph2 buildGraph2(Attributes attributes) { + String duration = attributes.getValue(ATTR_DURATION); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + String count = attributes.getValue(ATTR_COUNT); + String fails = attributes.getValue(ATTR_FAILS); + Graph2 graph2 = new Graph2(duration == null ? 0 : convert(Integer.class, duration, 0)); + + if (sum != null) { + graph2.setSum(sum); + } + + if (avg != null) { + graph2.setAvg(avg); + } + + if (count != null) { + graph2.setCount(count); + } + + if (fails != null) { + graph2.setFails(fails); + } + + return graph2; + } + + @Override + public GraphTrend buildGraphTrend(Attributes attributes) { + String duration = attributes.getValue(ATTR_DURATION); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + String count = attributes.getValue(ATTR_COUNT); + String fails = attributes.getValue(ATTR_FAILS); + GraphTrend graphTrend = new GraphTrend(duration == null ? 0 : convert(Integer.class, duration, 0)); + + if (sum != null) { + graphTrend.setSum(sum); + } + + if (avg != null) { + graphTrend.setAvg(avg); + } + + if (count != null) { + graphTrend.setCount(count); + } + + if (fails != null) { + graphTrend.setFails(fails); + } + + return graphTrend; + } + + @Override + public String buildIp(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public Machine buildMachine(Attributes attributes) { + String ip = attributes.getValue(ATTR_IP); + Machine machine = new Machine(ip); + + return machine; + } + + @Override + public TransactionName buildName(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String min = attributes.getValue(ATTR_MIN); + String max = attributes.getValue(ATTR_MAX); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String sum2 = attributes.getValue(ATTR_SUM2); + String std = attributes.getValue(ATTR_STD); + String tps = attributes.getValue(ATTR_TPS); + String line95Value = attributes.getValue(ATTR_LINE95VALUE); + String line99Value = attributes.getValue(ATTR_LINE99VALUE); + String line999Value = attributes.getValue(ATTR_LINE999VALUE); + String line90Value = attributes.getValue(ATTR_LINE90VALUE); + String line50Value = attributes.getValue(ATTR_LINE50VALUE); + String line9999Value = attributes.getValue(ATTR_LINE9999VALUE); + TransactionName name = new TransactionName(id); + + if (totalCount != null) { + name.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + name.setFailCount(convert(Long.class, failCount, 0L)); + } + + if (failPercent != null) { + name.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (min != null) { + name.setMin(toNumber(min, "0.00", 0).doubleValue()); + } + + if (max != null) { + name.setMax(toNumber(max, "0.00", 0).doubleValue()); + } + + if (avg != null) { + name.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (sum != null) { + name.setSum(toNumber(sum, "0.0", 0).doubleValue()); + } + + if (sum2 != null) { + name.setSum2(toNumber(sum2, "0.0", 0).doubleValue()); + } + + if (std != null) { + name.setStd(toNumber(std, "0.0", 0).doubleValue()); + } + + if (tps != null) { + name.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + if (line95Value != null) { + name.setLine95Value(toNumber(line95Value, "0.00", 0).doubleValue()); + } + + if (line99Value != null) { + name.setLine99Value(toNumber(line99Value, "0.00", 0).doubleValue()); + } + + if (line999Value != null) { + name.setLine999Value(toNumber(line999Value, "0.00", 0).doubleValue()); + } + + if (line90Value != null) { + name.setLine90Value(toNumber(line90Value, "0.00", 0).doubleValue()); + } + + if (line50Value != null) { + name.setLine50Value(toNumber(line50Value, "0.00", 0).doubleValue()); + } + + if (line9999Value != null) { + name.setLine9999Value(toNumber(line9999Value, "0.00", 0).doubleValue()); + } + + return name; + } + + @Override + public Range buildRange(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + String fails = attributes.getValue(ATTR_FAILS); + String min = attributes.getValue(ATTR_MIN); + String max = attributes.getValue(ATTR_MAX); + String line95Value = attributes.getValue(ATTR_LINE95VALUE); + String line99Value = attributes.getValue(ATTR_LINE99VALUE); + String line999Value = attributes.getValue(ATTR_LINE999VALUE); + String line90Value = attributes.getValue(ATTR_LINE90VALUE); + String line50Value = attributes.getValue(ATTR_LINE50VALUE); + String line9999Value = attributes.getValue(ATTR_LINE9999VALUE); + Range range = new Range(value == null ? 0 : convert(Integer.class, value, 0)); + + if (count != null) { + range.setCount(convert(Integer.class, count, 0)); + } + + if (sum != null) { + range.setSum(convert(Double.class, sum, 0.0)); + } + + if (avg != null) { + range.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (fails != null) { + range.setFails(convert(Integer.class, fails, 0)); + } + + if (min != null) { + range.setMin(toNumber(min, "0.00", 0).doubleValue()); + } + + if (max != null) { + range.setMax(toNumber(max, "0.00", 0).doubleValue()); + } + + if (line95Value != null) { + range.setLine95Value(toNumber(line95Value, "0.00", 0).doubleValue()); + } + + if (line99Value != null) { + range.setLine99Value(toNumber(line99Value, "0.00", 0).doubleValue()); + } + + if (line999Value != null) { + range.setLine999Value(toNumber(line999Value, "0.00", 0).doubleValue()); + } + + if (line90Value != null) { + range.setLine90Value(toNumber(line90Value, "0.00", 0).doubleValue()); + } + + if (line50Value != null) { + range.setLine50Value(toNumber(line50Value, "0.00", 0).doubleValue()); + } + + if (line9999Value != null) { + range.setLine9999Value(toNumber(line9999Value, "0.00", 0).doubleValue()); + } + + return range; + } + + @Override + public Range2 buildRange2(Attributes attributes) { + String value = attributes.getValue(ATTR_VALUE); + String count = attributes.getValue(ATTR_COUNT); + String sum = attributes.getValue(ATTR_SUM); + String avg = attributes.getValue(ATTR_AVG); + String fails = attributes.getValue(ATTR_FAILS); + String min = attributes.getValue(ATTR_MIN); + String max = attributes.getValue(ATTR_MAX); + String line95Value = attributes.getValue(ATTR_LINE95VALUE); + String line99Value = attributes.getValue(ATTR_LINE99VALUE); + String line999Value = attributes.getValue(ATTR_LINE999VALUE); + String line90Value = attributes.getValue(ATTR_LINE90VALUE); + String line50Value = attributes.getValue(ATTR_LINE50VALUE); + String line9999Value = attributes.getValue(ATTR_LINE9999VALUE); + Range2 range2 = new Range2(value == null ? 0 : convert(Integer.class, value, 0)); + + if (count != null) { + range2.setCount(convert(Integer.class, count, 0)); + } + + if (sum != null) { + range2.setSum(convert(Double.class, sum, 0.0)); + } + + if (avg != null) { + range2.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (fails != null) { + range2.setFails(convert(Integer.class, fails, 0)); + } + + if (min != null) { + range2.setMin(toNumber(min, "0.00", 0).doubleValue()); + } + + if (max != null) { + range2.setMax(toNumber(max, "0.00", 0).doubleValue()); + } + + if (line95Value != null) { + range2.setLine95Value(toNumber(line95Value, "0.00", 0).doubleValue()); + } + + if (line99Value != null) { + range2.setLine99Value(toNumber(line99Value, "0.00", 0).doubleValue()); + } + + if (line999Value != null) { + range2.setLine999Value(toNumber(line999Value, "0.00", 0).doubleValue()); + } + + if (line90Value != null) { + range2.setLine90Value(toNumber(line90Value, "0.00", 0).doubleValue()); + } + + if (line50Value != null) { + range2.setLine50Value(toNumber(line50Value, "0.00", 0).doubleValue()); + } + + if (line9999Value != null) { + range2.setLine9999Value(toNumber(line9999Value, "0.00", 0).doubleValue()); + } + + return range2; + } + + @Override + public StatusCode buildStatusCode(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String count = attributes.getValue(ATTR_COUNT); + StatusCode statusCode = new StatusCode(id); + + if (count != null) { + statusCode.setCount(convert(Long.class, count, 0L)); + } + + return statusCode; + } + + @Override + public TransactionReport buildTransactionReport(Attributes attributes) { + String domain = attributes.getValue(ATTR_DOMAIN); + String startTime = attributes.getValue(ATTR_STARTTIME); + String endTime = attributes.getValue(ATTR_ENDTIME); + TransactionReport transactionReport = new TransactionReport(domain); + + if (startTime != null) { + transactionReport.setStartTime(toDate(startTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + if (endTime != null) { + transactionReport.setEndTime(toDate(endTime, "yyyy-MM-dd HH:mm:ss", null)); + } + + return transactionReport; + } + + @Override + public TransactionType buildType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String totalCount = attributes.getValue(ATTR_TOTALCOUNT); + String failCount = attributes.getValue(ATTR_FAILCOUNT); + String failPercent = attributes.getValue(ATTR_FAILPERCENT); + String min = attributes.getValue(ATTR_MIN); + String max = attributes.getValue(ATTR_MAX); + String avg = attributes.getValue(ATTR_AVG); + String sum = attributes.getValue(ATTR_SUM); + String sum2 = attributes.getValue(ATTR_SUM2); + String std = attributes.getValue(ATTR_STD); + String tps = attributes.getValue(ATTR_TPS); + String line95Value = attributes.getValue(ATTR_LINE95VALUE); + String line99Value = attributes.getValue(ATTR_LINE99VALUE); + String line999Value = attributes.getValue(ATTR_LINE999VALUE); + String line90Value = attributes.getValue(ATTR_LINE90VALUE); + String line50Value = attributes.getValue(ATTR_LINE50VALUE); + String line9999Value = attributes.getValue(ATTR_LINE9999VALUE); + TransactionType type = new TransactionType(id); + + if (totalCount != null) { + type.setTotalCount(convert(Long.class, totalCount, 0L)); + } + + if (failCount != null) { + type.setFailCount(convert(Long.class, failCount, 0L)); + } + + if (failPercent != null) { + type.setFailPercent(toNumber(failPercent, "0.00", 0).doubleValue()); + } + + if (min != null) { + type.setMin(toNumber(min, "0.00", 0).doubleValue()); + } + + if (max != null) { + type.setMax(toNumber(max, "0.00", 0).doubleValue()); + } + + if (avg != null) { + type.setAvg(toNumber(avg, "0.0", 0).doubleValue()); + } + + if (sum != null) { + type.setSum(toNumber(sum, "0.0", 0).doubleValue()); + } + + if (sum2 != null) { + type.setSum2(toNumber(sum2, "0.0", 0).doubleValue()); + } + + if (std != null) { + type.setStd(toNumber(std, "0.0", 0).doubleValue()); + } + + if (tps != null) { + type.setTps(toNumber(tps, "0.00", 0).doubleValue()); + } + + if (line95Value != null) { + type.setLine95Value(toNumber(line95Value, "0.00", 0).doubleValue()); + } + + if (line99Value != null) { + type.setLine99Value(toNumber(line99Value, "0.00", 0).doubleValue()); + } + + if (line999Value != null) { + type.setLine999Value(toNumber(line999Value, "0.00", 0).doubleValue()); + } + + if (line90Value != null) { + type.setLine90Value(toNumber(line90Value, "0.00", 0).doubleValue()); + } + + if (line50Value != null) { + type.setLine50Value(toNumber(line50Value, "0.00", 0).doubleValue()); + } + + if (line9999Value != null) { + type.setLine9999Value(toNumber(line9999Value, "0.00", 0).doubleValue()); + } + + Map dynamicAttributes = type.getDynamicAttributes(); + int _length = attributes == null ? 0 : attributes.getLength(); + + for (int i = 0; i < _length; i++) { + String _name = attributes.getQName(i); + String _value = attributes.getValue(i); + + dynamicAttributes.put(_name, _value); + } + + dynamicAttributes.remove(ATTR_ID); + dynamicAttributes.remove(ATTR_TOTALCOUNT); + dynamicAttributes.remove(ATTR_FAILCOUNT); + dynamicAttributes.remove(ATTR_FAILPERCENT); + dynamicAttributes.remove(ATTR_MIN); + dynamicAttributes.remove(ATTR_MAX); + dynamicAttributes.remove(ATTR_AVG); + dynamicAttributes.remove(ATTR_SUM); + dynamicAttributes.remove(ATTR_SUM2); + dynamicAttributes.remove(ATTR_STD); + dynamicAttributes.remove(ATTR_TPS); + dynamicAttributes.remove(ATTR_LINE95VALUE); + dynamicAttributes.remove(ATTR_LINE99VALUE); + dynamicAttributes.remove(ATTR_LINE999VALUE); + dynamicAttributes.remove(ATTR_LINE90VALUE); + dynamicAttributes.remove(ATTR_LINE50VALUE); + dynamicAttributes.remove(ATTR_LINE9999VALUE); + + return type; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + protected java.util.Date toDate(String str, String format, java.util.Date defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format, Number defaultValue) { + if (str == null || str.length() == 0) { + return defaultValue; + } + + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..cb3ce4bcf1 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultSaxParser.java @@ -0,0 +1,488 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_DOMAIN_NAMES; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_FAILMESSAGEURL; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_IPS; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_LONGESTMESSAGEURL; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_SUCCESSMESSAGEURL; + +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH2; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE2; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_STATUSCODE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TRANSACTION_REPORT; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.consumer.transaction.model.IEntity; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static TransactionReport parse(InputStream in) throws SAXException, IOException { + return parseEntity(TransactionReport.class, new InputSource(removeBOM(in))); + } + + public static TransactionReport parse(Reader reader) throws SAXException, IOException { + return parseEntity(TransactionReport.class, new InputSource(removeBOM(reader))); + } + + public static TransactionReport parse(String xml) throws SAXException, IOException { + return parseEntity(TransactionReport.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof TransactionReport) { + TransactionReport transactionReport = (TransactionReport) currentObj; + + if (ELEMENT_DOMAIN.equals(currentTag)) { + transactionReport.addDomain(getText()); + } else if (ELEMENT_IP.equals(currentTag)) { + transactionReport.addIp(getText()); + } + } else if (currentObj instanceof TransactionType) { + TransactionType type = (TransactionType) currentObj; + + if (ELEMENT_SUCCESSMESSAGEURL.equals(currentTag)) { + type.setSuccessMessageUrl(getText()); + } else if (ELEMENT_FAILMESSAGEURL.equals(currentTag)) { + type.setFailMessageUrl(getText()); + } else if (ELEMENT_LONGESTMESSAGEURL.equals(currentTag)) { + type.setLongestMessageUrl(getText()); + } + } else if (currentObj instanceof TransactionName) { + TransactionName name = (TransactionName) currentObj; + + if (ELEMENT_SUCCESSMESSAGEURL.equals(currentTag)) { + name.setSuccessMessageUrl(getText()); + } else if (ELEMENT_FAILMESSAGEURL.equals(currentTag)) { + name.setFailMessageUrl(getText()); + } else if (ELEMENT_LONGESTMESSAGEURL.equals(currentTag)) { + name.setLongestMessageUrl(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAllDuration(AllDuration parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForDuration(Duration parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForGraph(Graph parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForGraph2(Graph2 parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForGraphTrend(GraphTrend parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForMachine(Machine parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_TYPE.equals(qName)) { + TransactionType type = m_maker.buildType(attributes); + + m_linker.onType(parentObj, type); + m_objs.push(type); + } else { + throw new SAXException(String.format("Element(%s) is not expected under machine!", qName)); + } + + m_tags.push(qName); + } + + private void parseForName(TransactionName parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_SUCCESSMESSAGEURL.equals(qName) || ELEMENT_FAILMESSAGEURL.equals(qName) || ELEMENT_LONGESTMESSAGEURL.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_RANGE.equals(qName)) { + Range range = m_maker.buildRange(attributes); + + m_linker.onRange(parentObj, range); + m_objs.push(range); + } else if (ENTITY_DURATION.equals(qName)) { + Duration duration = m_maker.buildDuration(attributes); + + m_linker.onDuration(parentObj, duration); + m_objs.push(duration); + } else if (ENTITY_GRAPH.equals(qName)) { + Graph graph = m_maker.buildGraph(attributes); + + m_linker.onGraph(parentObj, graph); + m_objs.push(graph); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_linker.onGraphTrend(parentObj, graphTrend); + m_objs.push(graphTrend); + } else if (ENTITY_STATUSCODE.equals(qName)) { + StatusCode statusCode = m_maker.buildStatusCode(attributes); + + m_linker.onStatusCode(parentObj, statusCode); + m_objs.push(statusCode); + } else { + throw new SAXException(String.format("Element(%s) is not expected under name!", qName)); + } + + m_tags.push(qName); + } + + private void parseForRange(Range parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForRange2(Range2 parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForStatusCode(StatusCode parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForTransactionReport(TransactionReport parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_DOMAIN_NAMES.equals(qName) || ELEMENT_DOMAIN.equals(qName) || ELEMENT_IPS.equals(qName) || ELEMENT_IP.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_linker.onMachine(parentObj, machine); + m_objs.push(machine); + } else { + throw new SAXException(String.format("Element(%s) is not expected under transaction-report!", qName)); + } + + m_tags.push(qName); + } + + private void parseForType(TransactionType parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_SUCCESSMESSAGEURL.equals(qName) || ELEMENT_FAILMESSAGEURL.equals(qName) || ELEMENT_LONGESTMESSAGEURL.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_NAME.equals(qName)) { + TransactionName name = m_maker.buildName(attributes); + + m_linker.onName(parentObj, name); + m_objs.push(name); + } else if (ENTITY_GRAPH2.equals(qName)) { + Graph2 graph2 = m_maker.buildGraph2(attributes); + + m_linker.onGraph2(parentObj, graph2); + m_objs.push(graph2); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_linker.onGraphTrend(parentObj, graphTrend); + m_objs.push(graphTrend); + } else if (ENTITY_RANGE2.equals(qName)) { + Range2 range2 = m_maker.buildRange2(attributes); + + m_linker.onRange2(parentObj, range2); + m_objs.push(range2); + } else { + throw new SAXException(String.format("Element(%s) is not expected under type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_TRANSACTION_REPORT.equals(qName)) { + TransactionReport transactionReport = m_maker.buildTransactionReport(attributes); + + m_entity = transactionReport; + m_objs.push(transactionReport); + m_tags.push(qName); + } else if (ENTITY_MACHINE.equals(qName)) { + Machine machine = m_maker.buildMachine(attributes); + + m_entity = machine; + m_objs.push(machine); + m_tags.push(qName); + } else if (ENTITY_TYPE.equals(qName)) { + TransactionType type = m_maker.buildType(attributes); + + m_entity = type; + m_objs.push(type); + m_tags.push(qName); + } else if (ENTITY_NAME.equals(qName)) { + TransactionName name = m_maker.buildName(attributes); + + m_entity = name; + m_objs.push(name); + m_tags.push(qName); + } else if (ENTITY_RANGE.equals(qName)) { + Range range = m_maker.buildRange(attributes); + + m_entity = range; + m_objs.push(range); + m_tags.push(qName); + } else if (ENTITY_DURATION.equals(qName)) { + Duration duration = m_maker.buildDuration(attributes); + + m_entity = duration; + m_objs.push(duration); + m_tags.push(qName); + } else if (ENTITY_RANGE2.equals(qName)) { + Range2 range2 = m_maker.buildRange2(attributes); + + m_entity = range2; + m_objs.push(range2); + m_tags.push(qName); + } else if (ENTITY_GRAPH.equals(qName)) { + Graph graph = m_maker.buildGraph(attributes); + + m_entity = graph; + m_objs.push(graph); + m_tags.push(qName); + } else if (ENTITY_GRAPH2.equals(qName)) { + Graph2 graph2 = m_maker.buildGraph2(attributes); + + m_entity = graph2; + m_objs.push(graph2); + m_tags.push(qName); + } else if (ENTITY_GRAPH_TREND.equals(qName)) { + GraphTrend graphTrend = m_maker.buildGraphTrend(attributes); + + m_entity = graphTrend; + m_objs.push(graphTrend); + m_tags.push(qName); + } else if (ENTITY_STATUSCODE.equals(qName)) { + StatusCode statusCode = m_maker.buildStatusCode(attributes); + + m_entity = statusCode; + m_objs.push(statusCode); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof TransactionReport) { + parseForTransactionReport((TransactionReport) parent, tag, qName, attributes); + } else if (parent instanceof Machine) { + parseForMachine((Machine) parent, tag, qName, attributes); + } else if (parent instanceof TransactionType) { + parseForType((TransactionType) parent, tag, qName, attributes); + } else if (parent instanceof TransactionName) { + parseForName((TransactionName) parent, tag, qName, attributes); + } else if (parent instanceof Range) { + parseForRange((Range) parent, tag, qName, attributes); + } else if (parent instanceof Duration) { + parseForDuration((Duration) parent, tag, qName, attributes); + } else if (parent instanceof Range2) { + parseForRange2((Range2) parent, tag, qName, attributes); + } else if (parent instanceof Graph) { + parseForGraph((Graph) parent, tag, qName, attributes); + } else if (parent instanceof Graph2) { + parseForGraph2((Graph2) parent, tag, qName, attributes); + } else if (parent instanceof GraphTrend) { + parseForGraphTrend((GraphTrend) parent, tag, qName, attributes); + } else if (parent instanceof AllDuration) { + parseForAllDuration((AllDuration) parent, tag, qName, attributes); + } else if (parent instanceof StatusCode) { + parseForStatusCode((StatusCode) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } + + protected java.util.Date toDate(String str, String format) { + try { + return new java.text.SimpleDateFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse date(%s) in format(%s)!", str, format), e); + } + } + + protected Number toNumber(String str, String format) { + try { + return new java.text.DecimalFormat(format).parse(str); + } catch (java.text.ParseException e) { + throw new RuntimeException(String.format("Unable to parse number(%s) in format(%s)!", str, format), e); + } + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultXmlBuilder.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..5dfc743f54 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/DefaultXmlBuilder.java @@ -0,0 +1,456 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_AVG; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_COUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DOMAIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ENDTIME; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILCOUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILPERCENT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_FAILS; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_ID; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_IP; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE50VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE90VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE95VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE9999VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE999VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_LINE99VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_MAX; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_MIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_STARTTIME; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_STD; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_SUM; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_SUM2; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_TOTALCOUNT; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_TPS; +import static com.dianping.cat.consumer.transaction.model.Constants.ATTR_VALUE; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_FAILMESSAGEURL; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_IP; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_LONGESTMESSAGEURL; +import static com.dianping.cat.consumer.transaction.model.Constants.ELEMENT_SUCCESSMESSAGEURL; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_ALL_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_DURATION; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH_TREND; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_GRAPH2; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_MACHINE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_NAME; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_RANGE2; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_STATUSCODE; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TRANSACTION_REPORT; +import static com.dianping.cat.consumer.transaction.model.Constants.ENTITY_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.consumer.transaction.model.IEntity; +import com.dianping.cat.consumer.transaction.model.IVisitor; +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + protected String toString(java.util.Date date, String format) { + if (date != null) { + return new java.text.SimpleDateFormat(format).format(date); + } else { + return null; + } + } + + protected String toString(Number number, String format) { + if (number != null) { + return new java.text.DecimalFormat(format).format(number); + } else { + return null; + } + } + + @Override + public void visitAllDuration(AllDuration allDuration) { + startTag(ENTITY_ALL_DURATION, true, null, ATTR_VALUE, allDuration.getValue(), ATTR_COUNT, allDuration.getCount()); + } + + @Override + public void visitDuration(Duration duration) { + startTag(ENTITY_DURATION, true, null, ATTR_VALUE, duration.getValue(), ATTR_COUNT, duration.getCount()); + } + + @Override + public void visitGraph(Graph graph) { + startTag(ENTITY_GRAPH, true, null, ATTR_DURATION, graph.getDuration(), ATTR_SUM, graph.getSum(), ATTR_AVG, graph.getAvg(), ATTR_COUNT, graph.getCount(), ATTR_FAILS, graph.getFails()); + } + + @Override + public void visitGraph2(Graph2 graph2) { + startTag(ENTITY_GRAPH2, true, null, ATTR_DURATION, graph2.getDuration(), ATTR_SUM, graph2.getSum(), ATTR_AVG, graph2.getAvg(), ATTR_COUNT, graph2.getCount(), ATTR_FAILS, graph2.getFails()); + } + + @Override + public void visitGraphTrend(GraphTrend graphTrend) { + startTag(ENTITY_GRAPH_TREND, true, null, ATTR_DURATION, graphTrend.getDuration(), ATTR_SUM, graphTrend.getSum(), ATTR_AVG, graphTrend.getAvg(), ATTR_COUNT, graphTrend.getCount(), ATTR_FAILS, graphTrend.getFails()); + } + + @Override + public void visitMachine(Machine machine) { + startTag(ENTITY_MACHINE, null, ATTR_IP, machine.getIp()); + + if (!machine.getTypes().isEmpty()) { + for (TransactionType type : machine.getTypes().values()) { + type.accept(m_visitor); + } + } + + endTag(ENTITY_MACHINE); + } + + @Override + public void visitName(TransactionName name) { + startTag(ENTITY_NAME, null, ATTR_ID, name.getId(), ATTR_TOTALCOUNT, name.getTotalCount(), ATTR_FAILCOUNT, name.getFailCount(), ATTR_FAILPERCENT, toString(name.getFailPercent(), "0.00"), ATTR_MIN, toString(name.getMin(), "0.00"), ATTR_MAX, toString(name.getMax(), "0.00"), ATTR_AVG, toString(name.getAvg(), "0.0"), ATTR_SUM, toString(name.getSum(), "0.0"), ATTR_SUM2, toString(name.getSum2(), "0.0"), ATTR_STD, toString(name.getStd(), "0.0"), ATTR_TPS, toString(name.getTps(), "0.00"), ATTR_LINE95VALUE, toString(name.getLine95Value(), "0.00"), ATTR_LINE99VALUE, toString(name.getLine99Value(), "0.00"), ATTR_LINE999VALUE, toString(name.getLine999Value(), "0.00"), ATTR_LINE90VALUE, toString(name.getLine90Value(), "0.00"), ATTR_LINE50VALUE, toString(name.getLine50Value(), "0.00"), ATTR_LINE9999VALUE, toString(name.getLine9999Value(), "0.00")); + + element(ELEMENT_SUCCESSMESSAGEURL, name.getSuccessMessageUrl(), null, true); + + element(ELEMENT_FAILMESSAGEURL, name.getFailMessageUrl(), null, true); + + element(ELEMENT_LONGESTMESSAGEURL, name.getLongestMessageUrl(), null, true); + + if (!name.getRanges().isEmpty()) { + for (Range range : name.getRanges().values()) { + range.accept(m_visitor); + } + } + + if (!name.getDurations().isEmpty()) { + for (Duration duration : name.getDurations().values()) { + duration.accept(m_visitor); + } + } + + if (!name.getGraphs().isEmpty()) { + for (Graph graph : name.getGraphs().values()) { + graph.accept(m_visitor); + } + } + + if (name.getGraphTrend() != null) { + name.getGraphTrend().accept(m_visitor); + } + + if (!name.getStatusCodes().isEmpty()) { + for (StatusCode statusCode : name.getStatusCodes().values()) { + statusCode.accept(m_visitor); + } + } + + endTag(ENTITY_NAME); + } + + @Override + public void visitRange(Range range) { + startTag(ENTITY_RANGE, true, null, ATTR_VALUE, range.getValue(), ATTR_COUNT, range.getCount(), ATTR_SUM, range.getSum(), ATTR_AVG, toString(range.getAvg(), "0.0"), ATTR_FAILS, range.getFails(), ATTR_MIN, toString(range.getMin(), "0.00"), ATTR_MAX, toString(range.getMax(), "0.00"), ATTR_LINE95VALUE, toString(range.getLine95Value(), "0.00"), ATTR_LINE99VALUE, toString(range.getLine99Value(), "0.00"), ATTR_LINE999VALUE, toString(range.getLine999Value(), "0.00"), ATTR_LINE90VALUE, toString(range.getLine90Value(), "0.00"), ATTR_LINE50VALUE, toString(range.getLine50Value(), "0.00"), ATTR_LINE9999VALUE, toString(range.getLine9999Value(), "0.00")); + } + + @Override + public void visitRange2(Range2 range2) { + startTag(ENTITY_RANGE2, true, null, ATTR_VALUE, range2.getValue(), ATTR_COUNT, range2.getCount(), ATTR_SUM, range2.getSum(), ATTR_AVG, toString(range2.getAvg(), "0.0"), ATTR_FAILS, range2.getFails(), ATTR_MIN, toString(range2.getMin(), "0.00"), ATTR_MAX, toString(range2.getMax(), "0.00"), ATTR_LINE95VALUE, toString(range2.getLine95Value(), "0.00"), ATTR_LINE99VALUE, toString(range2.getLine99Value(), "0.00"), ATTR_LINE999VALUE, toString(range2.getLine999Value(), "0.00"), ATTR_LINE90VALUE, toString(range2.getLine90Value(), "0.00"), ATTR_LINE50VALUE, toString(range2.getLine50Value(), "0.00"), ATTR_LINE9999VALUE, toString(range2.getLine9999Value(), "0.00")); + } + + @Override + public void visitStatusCode(StatusCode statusCode) { + startTag(ENTITY_STATUSCODE, true, null, ATTR_ID, statusCode.getId(), ATTR_COUNT, statusCode.getCount()); + } + + @Override + public void visitTransactionReport(TransactionReport transactionReport) { + startTag(ENTITY_TRANSACTION_REPORT, null, ATTR_DOMAIN, transactionReport.getDomain(), ATTR_STARTTIME, toString(transactionReport.getStartTime(), "yyyy-MM-dd HH:mm:ss"), ATTR_ENDTIME, toString(transactionReport.getEndTime(), "yyyy-MM-dd HH:mm:ss")); + + if (!transactionReport.getDomainNames().isEmpty()) { + for (String domain : transactionReport.getDomainNames()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!transactionReport.getIps().isEmpty()) { + for (String ip : transactionReport.getIps()) { + tagWithText(ELEMENT_IP, ip); + } + } + + if (!transactionReport.getMachines().isEmpty()) { + for (Machine machine : transactionReport.getMachines().values()) { + machine.accept(m_visitor); + } + } + + endTag(ENTITY_TRANSACTION_REPORT); + } + + @Override + public void visitType(TransactionType type) { + startTag(ENTITY_TYPE, type.getDynamicAttributes(), ATTR_ID, type.getId(), ATTR_TOTALCOUNT, type.getTotalCount(), ATTR_FAILCOUNT, type.getFailCount(), ATTR_FAILPERCENT, toString(type.getFailPercent(), "0.00"), ATTR_MIN, toString(type.getMin(), "0.00"), ATTR_MAX, toString(type.getMax(), "0.00"), ATTR_AVG, toString(type.getAvg(), "0.0"), ATTR_SUM, toString(type.getSum(), "0.0"), ATTR_SUM2, toString(type.getSum2(), "0.0"), ATTR_STD, toString(type.getStd(), "0.0"), ATTR_TPS, toString(type.getTps(), "0.00"), ATTR_LINE95VALUE, toString(type.getLine95Value(), "0.00"), ATTR_LINE99VALUE, toString(type.getLine99Value(), "0.00"), ATTR_LINE999VALUE, toString(type.getLine999Value(), "0.00"), ATTR_LINE90VALUE, toString(type.getLine90Value(), "0.00"), ATTR_LINE50VALUE, toString(type.getLine50Value(), "0.00"), ATTR_LINE9999VALUE, toString(type.getLine9999Value(), "0.00")); + + element(ELEMENT_SUCCESSMESSAGEURL, type.getSuccessMessageUrl(), null, true); + + element(ELEMENT_FAILMESSAGEURL, type.getFailMessageUrl(), null, true); + + element(ELEMENT_LONGESTMESSAGEURL, type.getLongestMessageUrl(), null, true); + + if (!type.getNames().isEmpty()) { + for (TransactionName name : type.getNames().values()) { + name.accept(m_visitor); + } + } + + if (!type.getGraph2s().isEmpty()) { + for (Graph2 graph2 : type.getGraph2s().values()) { + graph2.accept(m_visitor); + } + } + + if (type.getGraphTrend() != null) { + type.getGraphTrend().accept(m_visitor); + } + + if (!type.getRange2s().isEmpty()) { + for (Range2 range2 : type.getRange2s().values()) { + range2.accept(m_visitor); + } + } + + endTag(ENTITY_TYPE); + } +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/ILinker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/ILinker.java new file mode 100644 index 0000000000..82b15db5cd --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/ILinker.java @@ -0,0 +1,47 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public interface ILinker { + + public boolean onAllDuration(TransactionType parent, AllDuration allDuration); + + public boolean onAllDuration(TransactionName parent, AllDuration allDuration); + + public boolean onAllDuration(Range parent, AllDuration allDuration); + + public boolean onAllDuration(Range2 parent, AllDuration allDuration); + + public boolean onDuration(TransactionName parent, Duration duration); + + public boolean onGraph(TransactionName parent, Graph graph); + + public boolean onGraph2(TransactionType parent, Graph2 graph2); + + public boolean onGraphTrend(TransactionType parent, GraphTrend graphTrend); + + public boolean onGraphTrend(TransactionName parent, GraphTrend graphTrend); + + public boolean onMachine(TransactionReport parent, Machine machine); + + public boolean onName(TransactionType parent, TransactionName name); + + public boolean onRange(TransactionName parent, Range range); + + public boolean onRange2(TransactionType parent, Range2 range2); + + public boolean onStatusCode(TransactionName parent, StatusCode statusCode); + + public boolean onType(Machine parent, TransactionType type); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IMaker.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IMaker.java new file mode 100644 index 0000000000..74341d0490 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IMaker.java @@ -0,0 +1,45 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public interface IMaker { + + public AllDuration buildAllDuration(T node); + + public String buildDomain(T node); + + public Duration buildDuration(T node); + + public Graph buildGraph(T node); + + public Graph2 buildGraph2(T node); + + public GraphTrend buildGraphTrend(T node); + + public String buildIp(T node); + + public Machine buildMachine(T node); + + public TransactionName buildName(T node); + + public Range buildRange(T node); + + public Range2 buildRange2(T node); + + public StatusCode buildStatusCode(T node); + + public TransactionReport buildTransactionReport(T node); + + public TransactionType buildType(T node); +} diff --git a/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IParser.java b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IParser.java new file mode 100644 index 0000000000..1abfc72608 --- /dev/null +++ b/cat-consumer/src/main/java/com/dianping/cat/consumer/transaction/model/transform/IParser.java @@ -0,0 +1,40 @@ +package com.dianping.cat.consumer.transaction.model.transform; + +import com.dianping.cat.consumer.transaction.model.entity.AllDuration; +import com.dianping.cat.consumer.transaction.model.entity.Duration; +import com.dianping.cat.consumer.transaction.model.entity.Graph; +import com.dianping.cat.consumer.transaction.model.entity.Graph2; +import com.dianping.cat.consumer.transaction.model.entity.GraphTrend; +import com.dianping.cat.consumer.transaction.model.entity.Machine; +import com.dianping.cat.consumer.transaction.model.entity.Range; +import com.dianping.cat.consumer.transaction.model.entity.Range2; +import com.dianping.cat.consumer.transaction.model.entity.StatusCode; +import com.dianping.cat.consumer.transaction.model.entity.TransactionName; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; +import com.dianping.cat.consumer.transaction.model.entity.TransactionType; + +public interface IParser { + public TransactionReport parse(IMaker maker, ILinker linker, T node); + + public void parseForAllDuration(IMaker maker, ILinker linker, AllDuration parent, T node); + + public void parseForDuration(IMaker maker, ILinker linker, Duration parent, T node); + + public void parseForGraph(IMaker maker, ILinker linker, Graph parent, T node); + + public void parseForGraph2(IMaker maker, ILinker linker, Graph2 parent, T node); + + public void parseForGraphTrend(IMaker maker, ILinker linker, GraphTrend parent, T node); + + public void parseForMachine(IMaker maker, ILinker linker, Machine parent, T node); + + public void parseForTransactionName(IMaker maker, ILinker linker, TransactionName parent, T node); + + public void parseForRange(IMaker maker, ILinker linker, Range parent, T node); + + public void parseForRange2(IMaker maker, ILinker linker, Range2 parent, T node); + + public void parseForStatusCode(IMaker maker, ILinker linker, StatusCode parent, T node); + + public void parseForTransactionType(IMaker maker, ILinker linker, TransactionType parent, T node); +} diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/all-report-codegen.xml deleted file mode 100644 index e727d9fc17..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-codegen.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/all-report-manifest.xml deleted file mode 100644 index 1fdf6a7517..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/all-report-model.xml deleted file mode 100644 index 7497ef1cc0..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/all-report-model.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/business-report-codegen.xml deleted file mode 100644 index 954c069c3b..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-codegen.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/business-report-manifest.xml deleted file mode 100644 index dbc2b637fe..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/business-report-model.xml deleted file mode 100644 index 92da5f4625..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/business-report-model.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-codegen.xml deleted file mode 100644 index 74dec8fa2c..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-codegen.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-manifest.xml deleted file mode 100644 index 123b0821a8..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-model.xml deleted file mode 100644 index 528ac68034..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/cross-report-model.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-codegen.xml deleted file mode 100644 index 36322d4c9a..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-codegen.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-manifest.xml deleted file mode 100644 index 45093af1e1..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-model.xml deleted file mode 100644 index ebdc0835c3..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/dependency-report-model.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/event-report-codegen.xml deleted file mode 100644 index df13ef4fc9..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-codegen.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/event-report-manifest.xml deleted file mode 100644 index c1e7fc9036..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/event-report-model.xml deleted file mode 100644 index 6dd79d0660..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/event-report-model.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-codegen.xml deleted file mode 100644 index caaaf78b9a..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-codegen.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-manifest.xml deleted file mode 100644 index 898c1d6f42..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-model.xml deleted file mode 100644 index 80d2d729e9..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/heartbeat-report-model.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-codegen.xml deleted file mode 100644 index 5537c740b8..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-codegen.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-manifest.xml deleted file mode 100644 index d439fb9189..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-model.xml deleted file mode 100644 index fc11f32652..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/matrix-report-model.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-codegen.xml deleted file mode 100644 index 4b15b77c51..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-codegen.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-manifest.xml deleted file mode 100644 index 3a89d182d7..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-model.xml deleted file mode 100644 index d1fbb2dccf..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/problem-report-model.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/state-report-codegen.xml deleted file mode 100644 index 89116d9f34..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-codegen.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/state-report-manifest.xml deleted file mode 100644 index 9d2ad60bbe..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/state-report-model.xml deleted file mode 100644 index b6e9d2d296..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/state-report-model.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-codegen.xml deleted file mode 100644 index ca3934ee05..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-codegen.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-manifest.xml deleted file mode 100644 index 0608b67430..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-model.xml deleted file mode 100644 index c658a49592..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/storage-report-model.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/top-report-codegen.xml deleted file mode 100644 index 49fd8677fb..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-codegen.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/top-report-manifest.xml deleted file mode 100644 index fa0ee3c7ce..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/top-report-model.xml deleted file mode 100644 index 5c7f8da73f..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/top-report-model.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-codegen.xml deleted file mode 100644 index 9812bea130..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-codegen.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-manifest.xml deleted file mode 100644 index 47930634bd..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-model.xml deleted file mode 100644 index 83b46965e0..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/transaction-report-model.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml b/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml deleted file mode 100644 index 548fceeb43..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml b/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml deleted file mode 100644 index d873e11433..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-model.xml b/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-model.xml deleted file mode 100644 index 8f99bf19b9..0000000000 --- a/cat-consumer/src/main/resources/META-INF/dal/model/url-pattern-model.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/cat-consumer/src/main/resources/META-INF/plexus/components.xml b/cat-consumer/src/main/resources/META-INF/plexus/components.xml deleted file mode 100644 index 052cc8406b..0000000000 --- a/cat-consumer/src/main/resources/META-INF/plexus/components.xml +++ /dev/null @@ -1,836 +0,0 @@ - - - - - com.dianping.cat.analysis.MessageAnalyzer - transaction - com.dianping.cat.consumer.transaction.TransactionAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - transaction - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.config.transaction.TpValueStatisticConfigManager - - - com.dianping.cat.config.AtomicMessageConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - transaction - com.dianping.cat.consumer.transaction.TransactionDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.consumer.config.AllReportConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.config.AtomicMessageConfigManager - - - - - com.dianping.cat.report.ReportManager - transaction - com.dianping.cat.report.DefaultReportManager - per-lookup - - transaction - - - - com.dianping.cat.report.ReportDelegate - transaction - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - event - com.dianping.cat.consumer.event.EventAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - event - - - com.dianping.cat.config.AtomicMessageConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - event - com.dianping.cat.consumer.event.EventDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.consumer.config.AllReportConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.config.AtomicMessageConfigManager - - - - - com.dianping.cat.report.ReportManager - event - com.dianping.cat.report.DefaultReportManager - per-lookup - - event - - - - com.dianping.cat.report.ReportDelegate - event - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.consumer.problem.ProblemHandler - default-problem - com.dianping.cat.consumer.problem.DefaultProblemHandler - - Error,RuntimeException,Exception - - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.consumer.problem.ProblemHandler - long-execution - com.dianping.cat.consumer.problem.LongExecutionProblemHandler - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.analysis.MessageAnalyzer - problem - com.dianping.cat.consumer.problem.ProblemAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - problem - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.consumer.problem.ProblemHandler - m_handlers - - default-problem - long-execution - - - - - - com.dianping.cat.report.ReportManager - problem - com.dianping.cat.report.DefaultReportManager - per-lookup - - problem - - - - com.dianping.cat.report.ReportDelegate - problem - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.report.ReportDelegate - problem - com.dianping.cat.consumer.problem.ProblemDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - - - com.dianping.cat.analysis.MessageAnalyzer - heartbeat - com.dianping.cat.consumer.heartbeat.HeartbeatAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - heartbeat - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - heartbeat - com.dianping.cat.consumer.heartbeat.HeartbeatDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - - - com.dianping.cat.report.ReportManager - heartbeat - com.dianping.cat.report.DefaultReportManager - per-lookup - - heartbeat - - - - com.dianping.cat.report.ReportDelegate - heartbeat - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - top - com.dianping.cat.consumer.top.TopAnalyzer - per-lookup - - Error,RuntimeException,Exception - - - - com.dianping.cat.report.ReportManager - top - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - top - com.dianping.cat.consumer.top.TopDelegate - - - com.dianping.cat.report.ReportManager - top - com.dianping.cat.report.DefaultReportManager - per-lookup - - top - - - - com.dianping.cat.report.ReportDelegate - top - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - dump - com.dianping.cat.consumer.dump.DumpAnalyzer - per-lookup - - - com.dianping.cat.statistic.ServerStatisticManager - - - org.unidal.cat.message.storage.MessageDumperManager - - - org.unidal.cat.message.storage.MessageFinderManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.message.storage.MessageBucketManager - local - com.dianping.cat.consumer.dump.LocalMessageBucketManager - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.message.PathBuilder - - - com.dianping.cat.statistic.ServerStatisticManager - - - - - com.dianping.cat.analysis.MessageAnalyzer - state - com.dianping.cat.consumer.state.StateAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - state - - - com.dianping.cat.statistic.ServerStatisticManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.service.ProjectService - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - state - com.dianping.cat.consumer.state.StateDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.report.ReportBucketManager - - - - - com.dianping.cat.service.ProjectService - com.dianping.cat.service.ProjectService - - - com.dianping.cat.core.dal.ProjectDao - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportManager - state - com.dianping.cat.report.DefaultReportManager - per-lookup - - state - - - - com.dianping.cat.report.ReportDelegate - state - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - cross - com.dianping.cat.consumer.cross.CrossAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - cross - - - com.dianping.cat.consumer.cross.IpConvertManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - cross - com.dianping.cat.consumer.cross.CrossDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - - - com.dianping.cat.consumer.cross.IpConvertManager - com.dianping.cat.consumer.cross.IpConvertManager - - - com.dianping.cat.report.ReportManager - cross - com.dianping.cat.report.DefaultReportManager - per-lookup - - cross - - - - com.dianping.cat.report.ReportDelegate - cross - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - matrix - com.dianping.cat.consumer.matrix.MatrixAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - matrix - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - matrix - com.dianping.cat.consumer.matrix.MatrixDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - - - com.dianping.cat.report.ReportManager - matrix - com.dianping.cat.report.DefaultReportManager - per-lookup - - matrix - - - - com.dianping.cat.report.ReportDelegate - matrix - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - dependency - com.dianping.cat.consumer.dependency.DependencyAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - dependency - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.consumer.DatabaseParser - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - dependency - com.dianping.cat.consumer.dependency.DependencyDelegate - - - com.dianping.cat.task.TaskManager - - - - - com.dianping.cat.consumer.DatabaseParser - com.dianping.cat.consumer.DatabaseParser - - - com.dianping.cat.report.ReportManager - dependency - com.dianping.cat.report.DefaultReportManager - per-lookup - - dependency - - - - com.dianping.cat.report.ReportDelegate - dependency - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.consumer.storage.StorageReportUpdater - com.dianping.cat.consumer.storage.StorageReportUpdater - - - com.dianping.cat.consumer.storage.builder.StorageBuilderManager - com.dianping.cat.consumer.storage.builder.StorageBuilderManager - - - com.dianping.cat.consumer.storage.builder.StorageBuilder - SQL - com.dianping.cat.consumer.storage.builder.StorageSQLBuilder - - - com.dianping.cat.consumer.DatabaseParser - - - - - com.dianping.cat.consumer.storage.builder.StorageBuilder - Cache - com.dianping.cat.consumer.storage.builder.StorageCacheBuilder - - - com.dianping.cat.consumer.storage.builder.StorageBuilder - RPC - com.dianping.cat.consumer.storage.builder.StorageRPCBuilder - - - com.dianping.cat.analysis.MessageAnalyzer - storage - com.dianping.cat.consumer.storage.StorageAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - storage - - - com.dianping.cat.consumer.DatabaseParser - - - com.dianping.cat.consumer.storage.StorageReportUpdater - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - storage - com.dianping.cat.consumer.storage.StorageDelegate - - - com.dianping.cat.task.TaskManager - - - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.consumer.storage.StorageReportUpdater - - - - - com.dianping.cat.report.ReportManager - storage - com.dianping.cat.report.DefaultReportManager - per-lookup - - storage - - - - com.dianping.cat.report.ReportDelegate - storage - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.analysis.MessageAnalyzer - business - com.dianping.cat.consumer.business.BusinessAnalyzer - per-lookup - - - com.dianping.cat.report.ReportManager - business - - - com.dianping.cat.config.business.BusinessConfigManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportDelegate - business - com.dianping.cat.consumer.business.BusinessDelegate - - - com.dianping.cat.task.TaskManager - - - - - com.dianping.cat.report.ReportManager - business - com.dianping.cat.report.DefaultReportManager - per-lookup - - business - - - - com.dianping.cat.report.ReportDelegate - business - - - com.dianping.cat.report.ReportBucketManager - - - com.dianping.cat.core.dal.HourlyReportDao - - - com.dianping.cat.core.dal.HourlyReportContentDao - - - com.dianping.cat.report.DomainValidator - - - - - com.dianping.cat.config.AtomicMessageConfigManager - com.dianping.cat.config.AtomicMessageConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.config.server.ServerConfigManager - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.config.transaction.TpValueStatisticConfigManager - com.dianping.cat.config.transaction.TpValueStatisticConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.consumer.config.AllReportConfigManager - com.dianping.cat.consumer.config.AllReportConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - org.unidal.initialization.Module - cat-consumer - com.dianping.cat.consumer.CatConsumerModule - - - diff --git a/cat-consumer/src/main/resources/META-INF/wizard/jdbc/wizard.xml b/cat-consumer/src/main/resources/META-INF/wizard/jdbc/wizard.xml index b1e00faeab..dcab81b1f6 100644 --- a/cat-consumer/src/main/resources/META-INF/wizard/jdbc/wizard.xml +++ b/cat-consumer/src/main/resources/META-INF/wizard/jdbc/wizard.xml @@ -2,14 +2,14 @@ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://192.168.7.43:3306/cat dpcom_cat password useUnicode=true&autoReconnect=true -
+
diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/MockLog.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/MockLog.java deleted file mode 100644 index 5050a3b80a..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/MockLog.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer; - -import org.codehaus.plexus.logging.Logger; - -public class MockLog implements Logger { - - @Override - public void debug(String message) { - - } - - @Override - public void debug(String message, Throwable throwable) { - - } - - @Override - public boolean isDebugEnabled() { - - return false; - } - - @Override - public void info(String message) { - - } - - @Override - public void info(String message, Throwable throwable) { - - } - - @Override - public boolean isInfoEnabled() { - - return false; - } - - @Override - public void warn(String message) { - - } - - @Override - public void warn(String message, Throwable throwable) { - - } - - @Override - public boolean isWarnEnabled() { - - return false; - } - - @Override - public void error(String message) { - - } - - @Override - public void error(String message, Throwable throwable) { - - } - - @Override - public boolean isErrorEnabled() { - - return false; - } - - @Override - public void fatalError(String message) { - - } - - @Override - public void fatalError(String message, Throwable throwable) { - - } - - @Override - public boolean isFatalErrorEnabled() { - - return false; - } - - @Override - public Logger getChildLogger(String name) { - - return null; - } - - @Override - public int getThreshold() { - - return 0; - } - - @Override - public void setThreshold(int threshold) { - - } - - @Override - public String getName() { - - return null; - } - -} \ No newline at end of file diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/RealtimeConfigConfiguration.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/RealtimeConfigConfiguration.java deleted file mode 100644 index 47b23a0933..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/RealtimeConfigConfiguration.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.analysis.MessageAnalyzer; -import com.dianping.cat.analysis.MessageAnalyzerManager; -import com.dianping.cat.consumer.event.EventAnalyzer; -import com.dianping.cat.consumer.top.TopAnalyzer; -import com.dianping.cat.consumer.transaction.Configurator; -import com.dianping.cat.consumer.transaction.TransactionAnalyzer; -import com.dianping.cat.consumer.transaction.TransactionAnalyzerTest; - -public class RealtimeConfigConfiguration extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return TransactionAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - - return all; - } - - public static class MockMessageAnalyzerManager implements MessageAnalyzerManager { - - @Override - public List getAnalyzerNames() { - List list = new ArrayList(); - - list.add(TransactionAnalyzer.ID); - list.add(EventAnalyzer.ID); - list.add(TopAnalyzer.ID); - return list; - } - - @Override - public List getAnalyzer(String name, long startTime) { - return null; - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessAnalyzerTest.java deleted file mode 100644 index 8d8c79c7f6..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessAnalyzerTest.java +++ /dev/null @@ -1,137 +0,0 @@ -///* -// * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. -// * -// * Licensed to the Apache Software Foundation (ASF) under one or more -// * contributor license agreements. See the NOTICE file distributed with -// * this work for additional information regarding copyright ownership. -// * The ASF licenses this file to You under the Apache License, Version 2.0 -// * (the "License"); you may not use this file except in compliance with -// * the License. You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -//package com.dianping.cat.consumer.business; -// -//import java.text.SimpleDateFormat; -//import java.util.Date; -// -//import org.junit.Assert; -//import org.junit.Before; -//import org.junit.Test; -//import org.unidal.helper.Files; -//import org.unidal.lookup.ComponentTestCase; -// -//import com.dianping.cat.Constants; -//import com.dianping.cat.analysis.MessageAnalyzer; -//import com.dianping.cat.consumer.business.model.entity.BusinessReport; -//import com.dianping.cat.message.internal.DefaultEvent; -//import com.dianping.cat.message.internal.DefaultMetric; -//import com.dianping.cat.message.internal.DefaultTransaction; -//import com.dianping.cat.message.spi.MessageTree; -//import com.dianping.cat.message.spi.internal.DefaultMessageTree; -// -//public class BusinessAnalyzerTest extends ComponentTestCase { -// -// private final int MINITE = 60 * 1000; -// -// private long m_timestamp; -// -// private String m_domain = "group"; -// -// private BusinessAnalyzer m_analyzer; -// -// @Before -// public void setUp() throws Exception { -// super.setUp(); -// -// m_timestamp = System.currentTimeMillis() - System.currentTimeMillis() % (3600 * 1000); -// m_analyzer = (BusinessAnalyzer) lookup(MessageAnalyzer.class, BusinessAnalyzer.ID); -// SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); -// Date date = sdf.parse("20160308 00:00"); -// -// m_analyzer.initialize(date.getTime(), Constants.HOUR, Constants.MINUTE * 5); -// } -// -// @Test -// public void testProcess() throws Exception { -// for (int i = 1; i <= 60; i++) { -// MessageTree tree = ((DefaultMessageTree) generateMessageTree(i)).copyForTest(); -// -// m_analyzer.process(tree); -// } -// -// BusinessReport report = m_analyzer.getReport(m_domain); -// String expected = Files.forIO().readFrom(getClass().getResourceAsStream("business_analyzer.xml"), "utf-8"); -// -// Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); -// } -// -// protected MessageTree generateMessageTree(int i) { -// MessageTree tree = new DefaultMessageTree(); -// -// tree.setMessageId("" + i); -// tree.setDomain(m_domain); -// tree.setHostName("group001"); -// tree.setIpAddress("192.168.1.1"); -// -// DefaultTransaction t; -// -// if (i % 3 == 0) { -// t = new DefaultTransaction("URL", "TuanGouWeb", null); -// t.setTimestamp(m_timestamp + i * MINITE); -// DefaultEvent event = new DefaultEvent("URL", "ABTest"); -// -// DefaultMetric metric = new DefaultMetric("City", "/beijing"); -// -// metric.setTimestamp(m_timestamp + i * MINITE); -// metric.setStatus("S"); -// metric.addData("10"); -// -// t.addChild(metric); -// t.addChild(event); -// } else if (i % 3 == 1) { -// t = new DefaultTransaction("Service", "TuanGouWeb", null); -// t.setTimestamp(m_timestamp + i * MINITE); -// DefaultEvent event = new DefaultEvent("URL", "ABTest"); -// -// DefaultMetric metric = new DefaultMetric("", "/nanjing"); -// -// metric.setTimestamp(m_timestamp + i * MINITE); -// metric.setStatus("S,C"); -// metric.addData("10,10"); -// -// t.addChild(metric); -// t.addChild(event); -// } else { -// t = new DefaultTransaction("Metric", "TuanGouWeb", null); -// t.setTimestamp(m_timestamp + 1000); -// DefaultMetric metric = new DefaultMetric("", "/shanghai"); -// -// metric.setTimestamp(m_timestamp + i * MINITE); -// metric.setStatus("C"); -// metric.addData("10"); -// -// t.addChild(metric); -// -// DefaultMetric durationMetric = new DefaultMetric("", "/shenzhen"); -// -// durationMetric.setTimestamp(m_timestamp + i * MINITE); -// durationMetric.setStatus("T"); -// durationMetric.addData("10"); -// -// t.addChild(durationMetric); -// } -// -// t.complete(); -// t.setDurationInMillis(i * 2); -// tree.setMessage(t); -// -// return tree; -// } -//} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessReportMergerTest.java index ee0bf567b9..07341422a9 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/business/BusinessReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.business.model.entity.BusinessReport; import com.dianping.cat.consumer.business.model.transform.DefaultSaxParser; @@ -29,11 +28,11 @@ public class BusinessReportMergerTest { @Test public void testBusinessReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("business_base.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("business_merger.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("business_base.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("business_merger.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); BusinessReport reportOld = DefaultSaxParser.parse(oldXml); BusinessReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("business_merger_result.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("business_merger_result.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); BusinessReportMerger merger = new BusinessReportMerger(new BusinessReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/Configurator.java deleted file mode 100644 index 1065d7e53b..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/Configurator.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.cross; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.cross.model.entity.CrossReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -import static com.dianping.cat.Constants.HOUR; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return CrossAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = CrossAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockCrossReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedCrossDelegate.class)); - - return all; - } - - public static class ExtendedCrossDelegate extends CrossDelegate { - } - - public static class MockCrossReportManager extends MockReportManager { - private Map> m_reports = new ConcurrentHashMap>(); - - ; - - @Inject - private ReportDelegate m_delegate; - - @Override - public CrossReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - Map reports = m_reports.get(startTime); - - if (reports == null && createIfNotExist) { - reports = new ConcurrentHashMap(); - m_reports.put(startTime, reports); - } - - CrossReport report = reports.get(domain); - - if (report == null && createIfNotExist) { - report = m_delegate.makeReport(domain, startTime, HOUR); - reports.put(domain, report); - } - return report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossAnalyzerTest.java index a0831857af..cf4ab4ae90 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossAnalyzerTest.java @@ -20,24 +20,26 @@ import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Map; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.cross.model.entity.CrossReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.DefaultEvent; import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class CrossAnalyzerTest extends ComponentTestCase { +public class CrossAnalyzerTest { private long m_timestamp; @@ -47,14 +49,12 @@ public class CrossAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); long currentTimeMillis = System.currentTimeMillis(); m_timestamp = currentTimeMillis - currentTimeMillis % (3600 * 1000); - m_analyzer = (CrossAnalyzer) lookup(MessageAnalyzer.class, CrossAnalyzer.ID); - + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -70,11 +70,11 @@ public void testProcess() throws Exception { } CrossReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("cross_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("cross_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); CrossReport reportCaller = m_analyzer.getReport("server"); - String expectedCaller = Files.forIO().readFrom(getClass().getResourceAsStream("cross_analyzer_caller.xml"), "utf-8"); + String expectedCaller = new String(getClass().getResourceAsStream("cross_analyzer_caller.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expectedCaller.replaceAll("\r", ""), reportCaller.toString().replaceAll("\r", "")); } @@ -116,7 +116,7 @@ protected MessageTree generateMessageTree(int i) { t.addChild(eventApp); } - t.complete(); + t.setCompleted(); t.setDurationInMillis(i * 2); t.setTimestamp(m_timestamp + 1000); tree.setMessage(t); @@ -136,4 +136,54 @@ public void testFormatIp() { Assert.assertEquals("10.1.6.128", analyzer.convertHostNameToIP("10.1.6.128")); } + private CrossAnalyzer createAnalyzer() { + CrossAnalyzer analyzer = new CrossAnalyzer(); + + analyzer.setIpConvertManager(new IpConvertManager()); + analyzer.setReportManager(new MockCrossReportManager()); + analyzer.setServerConfigManager(new MockServerConfigManager()); + return analyzer; + } + + private static class MockCrossReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new CrossDelegate(); + + private Map> m_reports = new ConcurrentHashMap>(); + + @Override + public CrossReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + Map reports = m_reports.get(startTime); + + if (reports == null && createIfNotExist) { + reports = new ConcurrentHashMap(); + m_reports.put(startTime, reports); + } + + CrossReport report = reports.get(domain); + + if (report == null && createIfNotExist) { + report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + reports.put(domain, report); + } + return report; + } + + @Override + public void destory() { + } + } + + private static class MockServerConfigManager extends ServerConfigManager { + + @Override + public boolean isRpcClient(String type) { + return "PigeonCall".equals(type) || "Call".equals(type); + } + + @Override + public boolean isRpcServer(String type) { + return "PigeonService".equals(type) || "Service".equals(type); + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossInfoTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossInfoTest.java index b4bd25cf62..a5b7e98093 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossInfoTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossInfoTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.consumer.cross.CrossAnalyzer.CrossInfo; @@ -30,7 +29,7 @@ import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; -public class CrossInfoTest extends ComponentTestCase { +public class CrossInfoTest { public MessageTree buildMockMessageTree() { MessageTree tree = new DefaultMessageTree(); tree.setMessageId("Cat-c0a80746-373452-6");// 192.168.7.70 machine logview @@ -40,10 +39,7 @@ public MessageTree buildMockMessageTree() { @Test public void testParseOtherTransaction() throws Exception { - CrossAnalyzer analyzer = new CrossAnalyzer(); - - analyzer.setServerConfigManager(lookup(ServerConfigManager.class)); - analyzer.setIpConvertManager(new IpConvertManager()); + CrossAnalyzer analyzer = createAnalyzer(); DefaultTransaction t = new DefaultTransaction("Other", "method1"); MessageTree tree = buildMockMessageTree(); @@ -54,10 +50,7 @@ public void testParseOtherTransaction() throws Exception { @Test public void testParsePigeonClientTransaction() throws Exception { - CrossAnalyzer analyzer = new CrossAnalyzer(); - - analyzer.setServerConfigManager(lookup(ServerConfigManager.class)); - analyzer.setIpConvertManager(new IpConvertManager()); + CrossAnalyzer analyzer = createAnalyzer(); DefaultTransaction t = new DefaultTransaction("PigeonCall", "method1"); MessageTree tree = buildMockMessageTree(); @@ -82,10 +75,7 @@ public void testParsePigeonClientTransaction() throws Exception { @Test public void testParsePigeonServerTransaction() throws Exception { - CrossAnalyzer analyzer = new CrossAnalyzer(); - - analyzer.setServerConfigManager(lookup(ServerConfigManager.class)); - analyzer.setIpConvertManager(new IpConvertManager()); + CrossAnalyzer analyzer = createAnalyzer(); DefaultTransaction t = new DefaultTransaction("PigeonService", "method1"); MessageTree tree = buildMockMessageTree(); @@ -109,10 +99,7 @@ public void testParsePigeonServerTransaction() throws Exception { @Test public void testParsePigeonServerTransactionWithPort() throws Exception { - CrossAnalyzer analyzer = new CrossAnalyzer(); - - analyzer.setServerConfigManager(lookup(ServerConfigManager.class)); - analyzer.setIpConvertManager(new IpConvertManager()); + CrossAnalyzer analyzer = createAnalyzer(); DefaultTransaction t = new DefaultTransaction("PigeonService", "method1"); MessageTree tree = buildMockMessageTree(); @@ -131,4 +118,25 @@ public void testParsePigeonServerTransactionWithPort() throws Exception { Assert.assertEquals(info.getRemoteRole(), "Pigeon.Client"); Assert.assertEquals(info.getApp(), "myDomain"); } + + private CrossAnalyzer createAnalyzer() { + CrossAnalyzer analyzer = new CrossAnalyzer(); + + analyzer.setServerConfigManager(new MockServerConfigManager()); + analyzer.setIpConvertManager(new IpConvertManager()); + return analyzer; + } + + private static class MockServerConfigManager extends ServerConfigManager { + + @Override + public boolean isRpcClient(String type) { + return "PigeonCall".equals(type) || "Call".equals(type); + } + + @Override + public boolean isRpcServer(String type) { + return "PigeonService".equals(type) || "Service".equals(type); + } + } } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossReportMergerTest.java index a00947ba01..f729c26406 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/cross/CrossReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.cross.model.entity.CrossReport; import com.dianping.cat.consumer.cross.model.transform.DefaultSaxParser; @@ -28,11 +27,11 @@ public class CrossReportMergerTest { @Test public void testCrossReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("cross_analyzer_old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("cross_analyzer_old.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("cross_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("cross_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); CrossReport reportOld = DefaultSaxParser.parse(oldXml); CrossReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("cross_analyzer_merger.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("cross_analyzer_merger.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); CrossReportMerger merger = new CrossReportMerger(new CrossReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/dump/StoragePerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/dump/StoragePerformanceTest.java index 06c9118eb6..7bef6efcff 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/dump/StoragePerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/dump/StoragePerformanceTest.java @@ -19,38 +19,54 @@ package com.dianping.cat.consumer.dump; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Comparator; import org.junit.Before; import org.junit.Test; -import org.unidal.cat.message.storage.StorageConfiguration; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Cat; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.message.DefaultPathBuilder; import com.dianping.cat.message.codec.PlainTextMessageCodec; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageCodec; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.message.storage.LocalMessageBucket; +import com.dianping.cat.message.storage.MessageBucketFactory; import com.dianping.cat.message.storage.MessageBucketManager; import com.dianping.cat.message.tree.MessageId; +import com.dianping.cat.statistic.ServerStatisticManager; -public class StoragePerformanceTest extends ComponentTestCase { +public class StoragePerformanceTest { private MessageCodec m_codec = new PlainTextMessageCodec(); + private File m_baseDir; + @Before - public void before() { - File baseDir = new File(Cat.getCatHome(),"bucket/dump/20160415"); + public void before() throws IOException { + m_baseDir = new File(Cat.getCatHome(),"bucket/dump/20160415"); + + deleteDirectory(new File(m_baseDir, "dump").toPath()); + } - Files.forDir().delete(new File(baseDir, "dump"), true); + private void deleteDirectory(Path path) throws IOException { + if (!Files.exists(path)) { + return; + } - lookup(StorageConfiguration.class).setBaseDataDir(baseDir); + try (java.util.stream.Stream stream = Files.walk(path)) { + stream.sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } } @Test public void testManyDomainIpWrite() throws Exception { TreeHelper.init(m_codec); long start = System.currentTimeMillis(); - MessageBucketManager manager = lookup(MessageBucketManager.class, "local"); + MessageBucketManager manager = createLocalMessageBucketManager(); int hour = 405746; for (int i = 0; i < 10000; i++) { @@ -81,4 +97,46 @@ public void testManyDomainIpWrite() throws Exception { long duration = System.currentTimeMillis() - start; System.out.println("write cost" + duration); } + + private MessageBucketManager createLocalMessageBucketManager() { + LocalMessageBucketManager manager = new LocalMessageBucketManager(); + + manager.setBucketFactory(new MockMessageBucketFactory()); + manager.setConfigManager(new MockServerConfigManager()); + manager.setLocalIp("127.0.0.1"); + manager.setPathBuilder(new DefaultPathBuilder()); + manager.setServerStateManager(new ServerStatisticManager()); + manager.initialize(); + return manager; + } + + private class MockMessageBucketFactory implements MessageBucketFactory { + + @Override + public LocalMessageBucket createBucket(File baseDir, String dataFile) throws IOException { + LocalMessageBucket bucket = new LocalMessageBucket(); + + bucket.setBaseDir(baseDir); + bucket.initialize(dataFile); + return bucket; + } + } + + private class MockServerConfigManager extends ServerConfigManager { + + @Override + public String getHdfsLocalBaseDir(String id) { + return new File(m_baseDir, id).getPath(); + } + + @Override + public boolean isLocalMode() { + return true; + } + + @Override + public boolean isUseNewStorage() { + return false; + } + } } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/event/Configurator.java deleted file mode 100644 index eca3b6fd86..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/Configurator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.event; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.event.model.entity.EventReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return EventAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = EventAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockEventReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedEventDelegate.class)); - - return all; - } - - public static class ExtendedEventDelegate extends EventDelegate { - } - - public static class MockEventReportManager extends MockReportManager { - private EventReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public EventReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (EventReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - @Override - public void destory() { - } - } - -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventAnalyzerTest.java index 844f8ec6ae..dca24fb687 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventAnalyzerTest.java @@ -24,11 +24,11 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.event.model.entity.EventReport; import com.dianping.cat.message.Message; @@ -36,8 +36,9 @@ import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class EventAnalyzerTest extends ComponentTestCase { +public class EventAnalyzerTest { private long m_timestamp; @@ -47,12 +48,11 @@ public class EventAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); long currentTimeMillis = System.currentTimeMillis(); m_timestamp = currentTimeMillis - currentTimeMillis % (3600 * 1000); - m_analyzer = (EventAnalyzer) lookup(MessageAnalyzer.class, EventAnalyzer.ID); + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -69,7 +69,7 @@ public void testProcess() throws Exception { EventReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("event_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("event_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); EventReport expected4report = com.dianping.cat.consumer.event.model.transform.DefaultSaxParser.parse(expected); @@ -97,7 +97,7 @@ protected MessageTree generateMessageTree(int i) { event1.setTimestamp(m_timestamp + 5 * 60 * 1000); t2.addChild(event1); - t2.complete(); + t2.setCompleted(); t2.setDurationInMillis(i); t.addChild(t2); @@ -113,7 +113,7 @@ protected MessageTree generateMessageTree(int i) { event.setStatus(Message.SUCCESS); t.addChild(event); - t.complete(); + t.setCompleted(); t.setDurationInMillis(i * 2); t.setTimestamp(m_timestamp + 1000); t2.setTimestamp(m_timestamp + 2000); @@ -122,4 +122,51 @@ protected MessageTree generateMessageTree(int i) { return tree; } + private EventAnalyzer createAnalyzer() { + EventAnalyzer analyzer = new EventAnalyzer(); + + analyzer.setAtomicMessageConfigManager(new MockAtomicMessageConfigManager()); + analyzer.setReportManager(new MockEventReportManager()); + analyzer.setServerConfigManager(new MockServerConfigManager()); + return analyzer; + } + + private static class MockAtomicMessageConfigManager extends AtomicMessageConfigManager { + @Override + public int getMaxNameThreshold(String domain) { + return 200; + } + } + + private static class MockServerConfigManager extends ServerConfigManager { + @Override + public int getMaxTypeThreshold() { + return 100; + } + + @Override + public int getTypeNameLengthLimit() { + return 1000; + } + } + + private static class MockEventReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new EventDelegate(); + + private EventReport m_report; + + @Override + public EventReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventReportMergerTest.java index 5f2482071a..01377c63c3 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/event/EventReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.event.model.entity.EventReport; @@ -29,11 +28,11 @@ public class EventReportMergerTest { @Test public void testEventReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("event_report_old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("event_report_new.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("event_report_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("event_report_new.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); EventReport reportOld = DefaultSaxParser.parse(oldXml); EventReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("event_report_mergeResult.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("event_report_mergeResult.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); EventReportMerger merger = new EventReportMerger(new EventReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/Configurator.java deleted file mode 100644 index e48518caf6..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/Configurator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.heartbeat; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return HeartbeatAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = HeartbeatAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockHeartbeatReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedHeartbeatDelegate.class)); - - return all; - } - - public static class ExtendedHeartbeatDelegate extends HeartbeatDelegate { - } - - public static class MockHeartbeatReportManager extends MockReportManager { - private HeartbeatReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public HeartbeatReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (HeartbeatReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - @Override - public void destory() { - } - } - -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.java index d33830955e..13f4ad6afb 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.java @@ -25,19 +25,19 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerFilterConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; import com.dianping.cat.message.Heartbeat; import com.dianping.cat.message.internal.DefaultHeartbeat; import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class HeartbeatAnalyzerTest extends ComponentTestCase { +public class HeartbeatAnalyzerTest { private long m_timestamp; @@ -49,15 +49,12 @@ public class HeartbeatAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); m_timestamp = date.getTime(); - m_analyzer = (HeartbeatAnalyzer) lookup(MessageAnalyzer.class, HeartbeatAnalyzer.ID); - + m_analyzer = createAnalyzer(); m_analyzer.initialize(date.getTime(), Constants.HOUR, Constants.MINUTE * 5); } @@ -71,7 +68,7 @@ public void testProcess() throws Exception { HeartbeatReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("heartbeat_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("heartbeat_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); } @@ -89,7 +86,7 @@ protected MessageTree generateMessageTree(int i) throws IOException { t.addChild(heartbeat); - t.complete(); + t.setCompleted(); t.setDurationInMillis(i * 2); t.setTimestamp(m_timestamp + 1000); tree.setMessage(t); @@ -104,11 +101,46 @@ private Heartbeat newHeartbeat(String type, String name, long timestamp, String heartbeat.setTimestamp(timestamp); if (m_status == null) { - m_status = Files.forIO().readFrom(getClass().getResourceAsStream("status_info.xml"), "utf-8"); + m_status = new String(getClass().getResourceAsStream("status_info.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); } heartbeat.addData(m_status); return heartbeat; } + + private HeartbeatAnalyzer createAnalyzer() { + HeartbeatAnalyzer analyzer = new HeartbeatAnalyzer(); + + analyzer.setReportManager(new MockHeartbeatReportManager()); + analyzer.setServerFilterConfigManager(new MockServerFilterConfigManager()); + return analyzer; + } + + private static class MockHeartbeatReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new HeartbeatDelegate(); + + private HeartbeatReport m_report; + + @Override + public HeartbeatReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + + private static class MockServerFilterConfigManager extends ServerFilterConfigManager { + + @Override + public boolean validateDomain(String domain) { + return true; + } + } } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatReportMergerTest.java index b09dc2afea..835c7a5d33 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/heartbeat/HeartbeatReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.heartbeat.model.entity.HeartbeatReport; import com.dianping.cat.consumer.heartbeat.model.transform.DefaultSaxParser; @@ -28,11 +27,11 @@ public class HeartbeatReportMergerTest { @Test public void testHeartbeatReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("heartbeat_analyzer_old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("heartbeat_analyzer_old.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("heartbeat_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("heartbeat_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); HeartbeatReport reportOld = DefaultSaxParser.parse(oldXml); HeartbeatReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("heartbeat_analyzer_merge.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("heartbeat_analyzer_merge.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); HeartbeatReportMerger merger = new HeartbeatReportMerger(new HeartbeatReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/Configurator.java deleted file mode 100644 index e6fc27ec1d..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/Configurator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.matrix; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return MatrixAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = MatrixAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockMatrixReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedMatrixDelegate.class)); - - return all; - } - - public static class ExtendedMatrixDelegate extends MatrixDelegate { - } - - public static class MockMatrixReportManager extends MockReportManager { - private MatrixReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public MatrixReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (MatrixReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.java index 24081d7bc7..356ac1886d 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.java @@ -24,21 +24,21 @@ import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; import org.junit.Assert; -public class MatrixAnalyzerTest extends ComponentTestCase { +public class MatrixAnalyzerTest { private long m_timestamp; @@ -48,13 +48,12 @@ public class MatrixAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); long currentTimeMillis = System.currentTimeMillis(); m_timestamp = currentTimeMillis - currentTimeMillis % (3600 * 1000); - m_analyzer = (MatrixAnalyzer) lookup(MessageAnalyzer.class, MatrixAnalyzer.ID); + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -71,7 +70,7 @@ public void testProcess() throws Exception { MatrixReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("matrix_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("matrix_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); //Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); MatrixReport expected4report = com.dianping.cat.consumer.matrix.model.transform.DefaultSaxParser.parse(expected); @@ -103,9 +102,10 @@ protected MessageTree generateMessageTree(int i) { event.setTimestamp(m_timestamp + 5 * 60 * 1000); event.setDurationInMillis(i); event.setStatus(Message.SUCCESS); + event.setCompleted(); t.addChild(event); - t.complete(); + t.setCompleted(); t.setDurationInMillis(i * 2); t.setTimestamp(m_timestamp + 1000); tree.setMessage(t); @@ -113,4 +113,31 @@ protected MessageTree generateMessageTree(int i) { return tree; } + private MatrixAnalyzer createAnalyzer() { + MatrixAnalyzer analyzer = new MatrixAnalyzer(); + + analyzer.setReportManager(new MockMatrixReportManager()); + analyzer.setServerConfigManager(new ServerConfigManager()); + return analyzer; + } + + private static class MockMatrixReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new MatrixDelegate(); + + private MatrixReport m_report; + + @Override + public MatrixReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixModelTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixModelTest.java index 9cff367e17..283a9f1e9c 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixModelTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixModelTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.consumer.matrix.model.transform.DefaultSaxParser; @@ -28,13 +27,13 @@ public class MatrixModelTest { @Test public void testModel() throws Exception { - String source = Files.forIO().readFrom(getClass().getResourceAsStream("matrix.xml"), "utf-8"); + String source = new String(getClass().getResourceAsStream("matrix.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); MatrixReport report = DefaultSaxParser.parse(source); MatrixReportFilter filter = new MatrixReportFilter(); filter.setMaxSize(10); report.accept(filter); - String expected1 = Files.forIO().readFrom(getClass().getResourceAsStream("matrix_result.xml"), "utf-8"); + String expected1 = new String(getClass().getResourceAsStream("matrix_result.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expected1.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixReportMergerTest.java index 1169bbb395..b72f354d27 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/matrix/MatrixReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.consumer.matrix.model.transform.DefaultSaxParser; @@ -28,11 +27,11 @@ public class MatrixReportMergerTest { @Test public void testMatrixReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("matrix_analyzer.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("matrix_analyzer.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("matrix_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("matrix_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); MatrixReport reportOld = DefaultSaxParser.parse(oldXml); MatrixReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("matrix_analyzer_merger.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("matrix_analyzer_merger.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); MatrixReportMerger merger = new MatrixReportMerger(new MatrixReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossConfigurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossConfigurator.java deleted file mode 100644 index 1325471cc8..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossConfigurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.performance; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.cross.CrossAnalyzer; -import com.dianping.cat.consumer.cross.CrossDelegate; -import com.dianping.cat.consumer.cross.model.entity.CrossReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class CrossConfigurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new CrossConfigurator()); - } - - protected Class getTestClass() { - return CrossPerformanceTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = CrossAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockCrossReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedCrossDelegate.class)); - - return all; - } - - public static class ExtendedCrossDelegate extends CrossDelegate { - } - - public static class MockCrossReportManager extends MockReportManager { - private CrossReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public CrossReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (CrossReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(CrossReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossPerformanceTest.java index 5f6f7045eb..329ade98c6 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/CrossPerformanceTest.java @@ -23,7 +23,6 @@ import java.util.concurrent.ConcurrentHashMap; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; import com.dianping.cat.config.server.ServerConfigManager; @@ -36,7 +35,7 @@ import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; -public class CrossPerformanceTest extends ComponentTestCase { +public class CrossPerformanceTest { @Test public void test() throws Exception { diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/DumpPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/DumpPerformanceTest.java index b1c4bcfdca..bdb7db4399 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/DumpPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/DumpPerformanceTest.java @@ -19,28 +19,33 @@ package com.dianping.cat.consumer.performance; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; +import org.unidal.cat.message.storage.MessageDumper; +import org.unidal.cat.message.storage.MessageDumperManager; +import org.unidal.cat.message.storage.MessageFinder; +import org.unidal.cat.message.storage.MessageFinderManager; -import com.dianping.cat.analysis.MessageAnalyzer; import com.dianping.cat.consumer.dump.DumpAnalyzer; import com.dianping.cat.message.Message; import com.dianping.cat.message.context.MessageIdFactory; import com.dianping.cat.message.internal.MockMessageBuilder; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.message.tree.MessageId; +import com.dianping.cat.statistic.ServerStatisticManager; -public class DumpPerformanceTest extends ComponentTestCase { +import io.netty.buffer.ByteBuf; + +public class DumpPerformanceTest { private MessageIdFactory m_factory = new MessageIdFactory(); public void setUp() throws Exception { - super.setUp(); m_factory.initialize("test"); } @Test public void test() throws Exception { - DumpAnalyzer analyzer = (DumpAnalyzer) lookup(MessageAnalyzer.class, DumpAnalyzer.ID); + DumpAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); @@ -113,4 +118,63 @@ public MessageHolder define() { return tree; } + private DumpAnalyzer createAnalyzer() { + DumpAnalyzer analyzer = new DumpAnalyzer(); + + analyzer.setDumperManager(new MockMessageDumperManager()); + analyzer.setFinderManager(new MockMessageFinderManager()); + analyzer.setServerStatisticManager(new ServerStatisticManager()); + analyzer.initialize(System.currentTimeMillis(), 60 * 60 * 1000L, 5 * 60 * 1000L); + return analyzer; + } + + private static class MockMessageDumper implements MessageDumper { + + @Override + public void awaitTermination(int hour) throws InterruptedException { + } + + @Override + public void initialize(int hour) { + } + + @Override + public void process(MessageTree tree) { + } + } + + private static class MockMessageDumperManager implements MessageDumperManager { + private final MessageDumper m_dumper = new MockMessageDumper(); + + @Override + public void close(int hour) { + } + + @Override + public MessageDumper find(int hour) { + return m_dumper; + } + + @Override + public MessageDumper findOrCreate(int hour) { + return m_dumper; + } + } + + private static class MockMessageFinderManager implements MessageFinderManager { + + @Override + public void close(int hour) { + } + + @Override + public ByteBuf find(MessageId id) { + return null; + } + + @Override + public void register(int hour, MessageFinder finder) { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventConfigurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventConfigurator.java deleted file mode 100644 index a679324fd9..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventConfigurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.performance; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.event.EventAnalyzer; -import com.dianping.cat.consumer.event.EventDelegate; -import com.dianping.cat.consumer.event.model.entity.EventReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class EventConfigurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new EventConfigurator()); - } - - protected Class getTestClass() { - return EventPerformanceTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = EventAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockEventReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedEventDelegate.class)); - - return all; - } - - public static class ExtendedEventDelegate extends EventDelegate { - } - - public static class MockEventReportManager extends MockReportManager { - private EventReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public EventReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (EventReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(EventReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventPerformanceTest.java index fadfa8934e..75d79134dc 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/EventPerformanceTest.java @@ -19,20 +19,24 @@ package com.dianping.cat.consumer.performance; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.Constants; +import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.event.EventAnalyzer; +import com.dianping.cat.consumer.event.EventDelegate; +import com.dianping.cat.consumer.event.model.entity.EventReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.MockMessageBuilder; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class EventPerformanceTest extends ComponentTestCase { +public class EventPerformanceTest { @Test public void test() throws Exception { - EventAnalyzer analyzer = (EventAnalyzer) lookup(MessageAnalyzer.class, EventAnalyzer.ID); + EventAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); @@ -98,4 +102,38 @@ public MessageHolder define() { return tree; } + private EventAnalyzer createAnalyzer() { + EventAnalyzer analyzer = new EventAnalyzer(); + + analyzer.setAtomicMessageConfigManager(new MockAtomicMessageConfigManager()); + analyzer.setReportManager(new MockEventReportManager()); + return analyzer; + } + + private static class MockAtomicMessageConfigManager extends AtomicMessageConfigManager { + @Override + public int getMaxNameThreshold(String domain) { + return 200; + } + } + + private static class MockEventReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new EventDelegate(); + + private EventReport m_report; + + @Override + public EventReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixConfigurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixConfigurator.java deleted file mode 100644 index 452b8a3b0e..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixConfigurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.performance; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.matrix.MatrixAnalyzer; -import com.dianping.cat.consumer.matrix.MatrixDelegate; -import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class MatrixConfigurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new MatrixConfigurator()); - } - - protected Class getTestClass() { - return MatrixPerformanceTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = MatrixAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockMatrixReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedMatrixDelegate.class)); - - return all; - } - - public static class ExtendedMatrixDelegate extends MatrixDelegate { - } - - public static class MockMatrixReportManager extends MockReportManager { - private MatrixReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public MatrixReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (MatrixReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(MatrixReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixPerformanceTest.java index 05192a9e47..bd146c8614 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/MatrixPerformanceTest.java @@ -19,20 +19,24 @@ package com.dianping.cat.consumer.performance; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.Constants; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.matrix.MatrixAnalyzer; +import com.dianping.cat.consumer.matrix.MatrixDelegate; +import com.dianping.cat.consumer.matrix.model.entity.MatrixReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.MockMessageBuilder; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class MatrixPerformanceTest extends ComponentTestCase { +public class MatrixPerformanceTest { @Test public void test() throws Exception { - MatrixAnalyzer analyzer = (MatrixAnalyzer) lookup(MessageAnalyzer.class, MatrixAnalyzer.ID); + MatrixAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); long current = System.currentTimeMillis(); @@ -97,4 +101,31 @@ public MessageHolder define() { return tree; } + private MatrixAnalyzer createAnalyzer() { + MatrixAnalyzer analyzer = new MatrixAnalyzer(); + + analyzer.setReportManager(new MockMatrixReportManager()); + analyzer.setServerConfigManager(new ServerConfigManager()); + return analyzer; + } + + private static class MockMatrixReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new MatrixDelegate(); + + private MatrixReport m_report; + + @Override + public MatrixReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemConfigurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemConfigurator.java deleted file mode 100644 index 414ab1e4fc..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemConfigurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.performance; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.problem.ProblemAnalyzer; -import com.dianping.cat.consumer.problem.ProblemDelegate; -import com.dianping.cat.consumer.problem.model.entity.ProblemReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class ProblemConfigurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new ProblemConfigurator()); - } - - protected Class getTestClass() { - return ProblemPerformanceTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = ProblemAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockProblemReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedProblemDelegate.class)); - - return all; - } - - public static class ExtendedProblemDelegate extends ProblemDelegate { - } - - public static class MockProblemReportManager extends MockReportManager { - private ProblemReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public ProblemReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (ProblemReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(ProblemReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemPerformanceTest.java index 70d756e261..a71f09928c 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/ProblemPerformanceTest.java @@ -19,22 +19,25 @@ package com.dianping.cat.consumer.performance; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.Constants; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.problem.ProblemAnalyzer; +import com.dianping.cat.consumer.problem.ProblemDelegate; +import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.message.Event; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.DefaultEvent; import com.dianping.cat.message.internal.MockMessageBuilder; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class ProblemPerformanceTest extends ComponentTestCase { +public class ProblemPerformanceTest { @Test public void test() throws Exception { - ProblemAnalyzer analyzer = (ProblemAnalyzer) lookup(MessageAnalyzer.class, ProblemAnalyzer.ID); + ProblemAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); long current = System.currentTimeMillis(); @@ -50,7 +53,7 @@ public void test() throws Exception { @Test public void test2() throws Exception { - ProblemAnalyzer analyzer = (ProblemAnalyzer) lookup(MessageAnalyzer.class, ProblemAnalyzer.ID); + ProblemAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); long current = System.currentTimeMillis(); @@ -110,4 +113,30 @@ public MessageHolder define() { return tree; } + private ProblemAnalyzer createAnalyzer() { + ProblemAnalyzer analyzer = new ProblemAnalyzer(); + + analyzer.setReportManager(new MockProblemReportManager()); + return analyzer; + } + + private static class MockProblemReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new ProblemDelegate(); + + private ProblemReport m_report; + + @Override + public ProblemReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionConfigurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionConfigurator.java deleted file mode 100644 index e11c5fdbab..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionConfigurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.performance; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.transaction.TransactionAnalyzer; -import com.dianping.cat.consumer.transaction.TransactionDelegate; -import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class TransactionConfigurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new TransactionConfigurator()); - } - - protected Class getTestClass() { - return TransactionPerformanceTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = TransactionAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockTransactionReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedTransactionDelegate.class)); - - return all; - } - - public static class ExtendedTransactionDelegate extends TransactionDelegate { - } - - public static class MockTransactionReportManager extends MockReportManager { - private TransactionReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public TransactionReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (TransactionReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(TransactionReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionPerformanceTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionPerformanceTest.java index 27ac3dbe11..f24667dcf1 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionPerformanceTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/performance/TransactionPerformanceTest.java @@ -19,24 +19,27 @@ package com.dianping.cat.consumer.performance; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.Constants; +import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.config.server.ServerFilterConfigManager; +import com.dianping.cat.config.transaction.TpValueStatisticConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.transaction.TransactionAnalyzer; +import com.dianping.cat.consumer.transaction.TransactionDelegate; +import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.MockMessageBuilder; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class TransactionPerformanceTest extends ComponentTestCase { - - public void setUp() throws Exception { - super.setUp(); - } +public class TransactionPerformanceTest { @Test public void test() throws Exception { - TransactionAnalyzer analyzer = (TransactionAnalyzer) lookup(MessageAnalyzer.class, TransactionAnalyzer.ID); + TransactionAnalyzer analyzer = createAnalyzer(); MessageTree tree = buildMessage(); @@ -108,4 +111,55 @@ public MessageHolder define() { return tree; } + private TransactionAnalyzer createAnalyzer() { + TransactionAnalyzer analyzer = new TransactionAnalyzer(); + + analyzer.setAtomicMessageConfigManager(new MockAtomicMessageConfigManager()); + analyzer.setServerFilterConfigManager(new MockServerFilterConfigManager()); + analyzer.setTransactionReportManager(new MockTransactionReportManager()); + analyzer.setServerConfigManager(new ServerConfigManager()); + analyzer.setTpValueStatisticConfigManager(new MockTpValueStatisticConfigManager()); + return analyzer; + } + + private static class MockAtomicMessageConfigManager extends AtomicMessageConfigManager { + @Override + public int getMaxNameThreshold(String domain) { + return 200; + } + } + + private static class MockServerFilterConfigManager extends ServerFilterConfigManager { + @Override + public boolean discardTransaction(String type, String name) { + return false; + } + } + + private static class MockTpValueStatisticConfigManager extends TpValueStatisticConfigManager { + @Override + public boolean shouldStatistic(String type, String domain) { + return false; + } + } + + private static class MockTransactionReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new TransactionDelegate(); + + private TransactionReport m_report; + + @Override + public TransactionReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/Configurator.java deleted file mode 100644 index c03a3d42d2..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/Configurator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.problem; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.problem.model.entity.ProblemReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return ProblemAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = ProblemAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockProblemReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedProblemDelegate.class)); - - return all; - } - - public static class ExtendedProblemDelegate extends ProblemDelegate { - } - - public static class MockProblemReportManager extends MockReportManager { - private ProblemReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public ProblemReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (ProblemReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(ProblemReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.java index a83e4809b3..567855d0cb 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.java @@ -18,16 +18,16 @@ */ package com.dianping.cat.consumer.problem; +import java.util.Arrays; import java.text.SimpleDateFormat; import java.util.Date; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.message.Event; @@ -38,10 +38,11 @@ import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; import org.junit.Assert; -public class ProblemAnalyzerTest extends ComponentTestCase { +public class ProblemAnalyzerTest { private long m_timestamp; @@ -51,10 +52,8 @@ public class ProblemAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); - m_timestamp = 1385470800000L; - m_analyzer = (ProblemAnalyzer) lookup(MessageAnalyzer.class, ProblemAnalyzer.ID); + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -71,7 +70,7 @@ public void testProcess() throws Exception { ProblemReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("problem_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("problem_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReport expected4report = com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser.parse(expected); Assert.assertTrue(TestHelper.isEquals(expected4report,report)); @@ -134,6 +133,8 @@ protected MessageTree generateMessageTree(int i) { DefaultTransaction transaction = new DefaultTransaction("Transaction", "Transaction"); transaction.setStatus(Transaction.SUCCESS); + transaction.setCompleted(); + t.setCompleted(); t.addChild(transaction); t.addChild(error); t.addChild(exception); @@ -143,4 +144,36 @@ protected MessageTree generateMessageTree(int i) { return tree; } + private ProblemAnalyzer createAnalyzer() { + ProblemAnalyzer analyzer = new ProblemAnalyzer(); + DefaultProblemHandler defaultProblemHandler = new DefaultProblemHandler(); + LongExecutionProblemHandler longExecutionProblemHandler = new LongExecutionProblemHandler(); + + defaultProblemHandler.setErrorType("Error,RuntimeException,Exception"); + longExecutionProblemHandler.setConfigManager(new ServerConfigManager()); + + analyzer.setReportManager(new MockProblemReportManager()); + analyzer.setHandlers(Arrays.asList(defaultProblemHandler, longExecutionProblemHandler)); + return analyzer; + } + + private static class MockProblemReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new ProblemDelegate(); + + private ProblemReport m_report; + + @Override + public ProblemReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemFilterTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemFilterTest.java index 4a5a3e4a01..39c3974575 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemFilterTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemFilterTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser; @@ -30,8 +29,8 @@ public class ProblemFilterTest { @Test public void test() throws Exception { ProblemReportFilter problemReportURLFilter = new ProblemReportFilter(5); - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("problemURLFilter.xml"), "utf-8"); - String resultXml = Files.forIO().readFrom(getClass().getResourceAsStream("problemURLFilterResult.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("problemURLFilter.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String resultXml = new String(getClass().getResourceAsStream("problemURLFilterResult.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReport report = DefaultSaxParser.parse(oldXml); problemReportURLFilter.visitProblemReport(report); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportConvertorTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportConvertorTest.java index 52a22f10a2..9fefd39637 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportConvertorTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportConvertorTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser; @@ -29,8 +28,8 @@ public class ProblemReportConvertorTest { @Test public void test() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("problemReportForConvert.xml"), "utf-8"); - String result = Files.forIO().readFrom(getClass().getResourceAsStream("problemReportConvertResult.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("problemReportForConvert.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String result = new String(getClass().getResourceAsStream("problemReportConvertResult.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReport report = DefaultSaxParser.parse(oldXml); ProblemReportConvertor convertor = new ProblemReportConvertor(); report.accept(convertor); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportMergerTest.java index 1c55b52459..6b3b87fc80 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportMergerTest.java @@ -23,7 +23,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser; @@ -31,11 +30,11 @@ public class ProblemReportMergerTest { @Test public void testProblemReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("ProblemReportOld.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("ProblemReportNew.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("ProblemReportOld.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("ProblemReportNew.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReport reportOld = DefaultSaxParser.parse(oldXml); ProblemReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("ProblemReportMergeResult.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("ProblemReportMergeResult.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReportMerger merger = new ProblemReportMerger(new ProblemReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportTest.java index 5cf0d71c50..f64ed0c446 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/problem/ProblemReportTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.problem.model.entity.ProblemReport; import com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser; @@ -29,7 +28,7 @@ public class ProblemReportTest { @Test public void testXml() throws Exception { - String source = Files.forIO().readFrom(getClass().getResourceAsStream("problem-report.xml"), "utf-8"); + String source = new String(getClass().getResourceAsStream("problem-report.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); ProblemReport root = DefaultSaxParser.parse(source); String xml = new DefaultXmlBuilder().buildXml(root); String expected = source; diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/state/Configurator.java deleted file mode 100644 index 71905fb01c..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/Configurator.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.state; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; -import com.dianping.cat.config.server.ServerConfigManager; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.state.model.entity.StateReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; -import com.dianping.cat.statistic.ServerStatisticManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return StateAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = StateAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockStateReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedStateDelegate.class)); - all.add(C(MessageAnalyzer.class, ID, StateAnalyzer.class).req(ReportManager.class, ID) - .req(ServerConfigManager.class, ServerStatisticManager.class).config(E("m_ip").value("192.168.1.1"))); - - return all; - } - - public static class ExtendedStateDelegate extends StateDelegate { - } - - public static class MockStateReportManager extends MockReportManager { - private StateReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public StateReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (StateReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - @Override - public void destory() { - } - } - -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateAnalyzerTest.java index cf56488681..5ae5e61c2f 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateAnalyzerTest.java @@ -25,14 +25,17 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerFilterConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.state.model.entity.StateReport; +import com.dianping.cat.core.dal.Project; +import com.dianping.cat.report.ReportDelegate; +import com.dianping.cat.service.ProjectService; +import com.dianping.cat.statistic.ServerStatisticManager; -public class StateAnalyzerTest extends ComponentTestCase { +public class StateAnalyzerTest { private StateAnalyzer m_analyzer; @@ -40,14 +43,12 @@ public class StateAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm:ss:SS"); Date date = sdf.parse("20120101 00:00:00:00"); - m_analyzer = (StateAnalyzer) lookup(MessageAnalyzer.class, StateAnalyzer.ID); - + m_analyzer = createAnalyzer(); m_analyzer.initialize(date.getTime(), Constants.HOUR, Constants.MINUTE * 5); } @@ -55,8 +56,59 @@ public void setUp() throws Exception { public void testProcess() throws Exception { StateReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("state_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("state_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); } + + private StateAnalyzer createAnalyzer() { + StateAnalyzer analyzer = new StateAnalyzer(); + + analyzer.setMIp("192.168.1.1"); + analyzer.setProjectService(new MockProjectService()); + analyzer.setReportManager(new MockStateReportManager()); + analyzer.setServerFilterConfigManager(new MockServerFilterConfigManager()); + analyzer.setServerStateManager(new ServerStatisticManager()); + return analyzer; + } + + private static class MockProjectService extends ProjectService { + + @Override + public Project findProject(String domain) { + return null; + } + + @Override + public boolean insert(String domain) { + return true; + } + } + + private static class MockServerFilterConfigManager extends ServerFilterConfigManager { + + @Override + public boolean validateDomain(String domain) { + return true; + } + } + + private static class MockStateReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new StateDelegate(); + + private StateReport m_report; + + @Override + public StateReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateReportMergerTest.java index 4eb4a3e506..9b42b654a8 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/state/StateReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.state.model.entity.StateReport; import com.dianping.cat.consumer.state.model.transform.DefaultSaxParser; @@ -28,11 +27,11 @@ public class StateReportMergerTest { @Test public void testStateReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("new.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("new.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); StateReport reportOld = DefaultSaxParser.parse(oldXml); StateReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("result.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("result.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); StateReportMerger merger = new StateReportMerger(new StateReport(reportOld.getDomain())); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/storage/DatabaseParserTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/storage/DatabaseParserTest.java index 2e3b3bda39..1a49e1ce7b 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/storage/DatabaseParserTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/storage/DatabaseParserTest.java @@ -20,16 +20,15 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.consumer.DatabaseParser; import com.dianping.cat.consumer.DatabaseParser.Database; -public class DatabaseParserTest extends ComponentTestCase { +public class DatabaseParserTest { @Test public void testOracle() { - DatabaseParser parser = lookup(DatabaseParser.class); + DatabaseParser parser = new DatabaseParser(); Database database = parser.parseDatabase("jdbc:oracle:thin:@ 172.20.70.36:1521:gbst"); Assert.assertEquals("172.20.70.36", database.getIp()); @@ -38,7 +37,7 @@ public void testOracle() { @Test public void testMysql() { - DatabaseParser parser = lookup(DatabaseParser.class); + DatabaseParser parser = new DatabaseParser(); Database database = parser.parseDatabase("jdbc:mysql://localhost:3306/mydb"); Assert.assertEquals("localhost", database.getIp()); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/top/Configurator.java deleted file mode 100644 index 750d2a79d3..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/Configurator.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.top; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.top.model.entity.TopReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return TopAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = TopAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockTopReportManager.class)// - .req(ReportDelegate.class, ID).is(PER_LOOKUP)); - all.add(C(ReportDelegate.class, ID, ExtendedTopDelegate.class)); - - return all; - } - - public static class ExtendedTopDelegate extends TopDelegate { - } - - public static class MockTopReportManager extends MockReportManager { - private TopReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public TopReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (TopReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopAnalyzerTest.java index dd6eed359a..0a96cb8a75 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopAnalyzerTest.java @@ -24,11 +24,10 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.server.ServerFilterConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.top.model.entity.TopReport; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.message.Event; @@ -39,8 +38,9 @@ import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class TopAnalyzerTest extends ComponentTestCase { +public class TopAnalyzerTest { private long m_timestamp; @@ -50,10 +50,8 @@ public class TopAnalyzerTest extends ComponentTestCase { @Before public void setUp() throws Exception { - super.setUp(); - m_timestamp = 1385470800000L; - m_analyzer = (TopAnalyzer) lookup(MessageAnalyzer.class, TopAnalyzer.ID); + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -70,7 +68,7 @@ public void testProcess() throws Exception { TopReport report = m_analyzer.getReport(m_domain); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("top_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("top_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertEquals(expected.replaceAll("\r", ""), report.toString().replaceAll("\r", "")); } @@ -115,4 +113,39 @@ protected MessageTree generateMessageTree(int i) { return tree; } + private TopAnalyzer createAnalyzer() { + TopAnalyzer analyzer = new TopAnalyzer(); + + analyzer.setReportManager(new MockTopReportManager()); + analyzer.setServerFilterConfigManager(new MockServerFilterConfigManager()); + analyzer.setErrorType("Error,RuntimeException,Exception"); + return analyzer; + } + + private static class MockServerFilterConfigManager extends ServerFilterConfigManager { + @Override + public boolean validateDomain(String domain) { + return true; + } + } + + private static class MockTopReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new TopDelegate(); + + private TopReport m_report; + + @Override + public TopReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } + } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopReportMergerTest.java index 74e074038e..1034787c35 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/top/TopReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.top.model.entity.TopReport; import com.dianping.cat.consumer.top.model.transform.DefaultSaxParser; @@ -28,11 +27,11 @@ public class TopReportMergerTest { @Test public void testTopReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("top_analyzer_old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("top_analyzer_old.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("top_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("top_analyzer_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); TopReport reportOld = DefaultSaxParser.parse(oldXml); TopReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("top_analyzer_merger.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("top_analyzer_merger.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); TopReportMerger merger = new TopReportMerger(new TopReport(reportOld.getDomain())); reportOld.accept(merger); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/Configurator.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/Configurator.java deleted file mode 100644 index 33cacf406e..0000000000 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/Configurator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.consumer.transaction; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.configuration.AbstractResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -import com.dianping.cat.Constants; -import com.dianping.cat.consumer.MockReportManager; -import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; -import com.dianping.cat.report.ReportDelegate; -import com.dianping.cat.report.ReportManager; - -public class Configurator extends AbstractResourceConfigurator { - - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new Configurator()); - } - - protected Class getTestClass() { - return TransactionAnalyzerTest.class; - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - final String ID = TransactionAnalyzer.ID; - - all.add(C(ReportManager.class, ID, MockTransactionReportManager.class)// - .req(ReportDelegate.class, ID)); - all.add(C(ReportDelegate.class, ID, ExtendedTransactionDelegate.class)); - - return all; - } - - public static class ExtendedTransactionDelegate extends TransactionDelegate { - } - - public static class MockTransactionReportManager extends MockReportManager { - private TransactionReport m_report; - - @Inject - private ReportDelegate m_delegate; - - @Override - public TransactionReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { - if (m_report == null) { - m_report = (TransactionReport) m_delegate.makeReport(domain, startTime, Constants.HOUR); - } - - return m_report; - } - - public void setReport(TransactionReport report) { - m_report = report; - } - - @Override - public void destory() { - } - } -} diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.java index 7e8cfbfed3..3247d4ff60 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.java @@ -24,19 +24,22 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.helper.Files; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.Constants; -import com.dianping.cat.analysis.MessageAnalyzer; +import com.dianping.cat.config.AtomicMessageConfigManager; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.config.server.ServerFilterConfigManager; +import com.dianping.cat.config.transaction.TpValueStatisticConfigManager; +import com.dianping.cat.consumer.MockReportManager; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; import com.dianping.cat.message.Message; import com.dianping.cat.message.internal.DefaultTransaction; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; +import com.dianping.cat.report.ReportDelegate; -public class TransactionAnalyzerTest extends ComponentTestCase { +public class TransactionAnalyzerTest { private long m_timestamp; private TransactionAnalyzer m_analyzer; @@ -59,10 +62,8 @@ public static void main(String[] args) { @Before public void setUp() throws Exception { - super.setUp(); - m_timestamp = System.currentTimeMillis() - System.currentTimeMillis() % (3600 * 1000); - m_analyzer = (TransactionAnalyzer) lookup(MessageAnalyzer.class, TransactionAnalyzer.ID); + m_analyzer = createAnalyzer(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm"); Date date = sdf.parse("20120101 00:00"); @@ -81,7 +82,7 @@ public void testProcess() throws Exception { report.accept(new TransactionStatisticsComputer()); - String expected = Files.forIO().readFrom(getClass().getResourceAsStream("transaction_analyzer.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("transaction_analyzer.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); Assert.assertTrue( TestHelper.isEquals(com.dianping.cat.consumer.transaction.model.transform.DefaultSaxParser.parse(expected), report)); } @@ -102,7 +103,7 @@ protected MessageTree generateMessageTree(int i) { t2.setStatus(Message.SUCCESS); } - t2.complete(); + t2.setCompleted(); t2.setDurationInMillis(i); t.addChild(t2); @@ -113,7 +114,7 @@ protected MessageTree generateMessageTree(int i) { t.setStatus(Message.SUCCESS); } - t.complete(); + t.setCompleted(); t.setDurationInMillis(i * 2); t.setTimestamp(m_timestamp + 1000); t2.setTimestamp(m_timestamp + 2000); @@ -121,4 +122,76 @@ protected MessageTree generateMessageTree(int i) { return tree; } + + private TransactionAnalyzer createAnalyzer() { + TransactionAnalyzer analyzer = new TransactionAnalyzer(); + + analyzer.setAtomicMessageConfigManager(new MockAtomicMessageConfigManager()); + analyzer.setServerFilterConfigManager(new MockServerFilterConfigManager()); + analyzer.setTransactionReportManager(new MockTransactionReportManager()); + analyzer.setServerConfigManager(new MockServerConfigManager()); + analyzer.setTpValueStatisticConfigManager(new MockTpValueStatisticConfigManager()); + return analyzer; + } + + private static class MockAtomicMessageConfigManager extends AtomicMessageConfigManager { + + @Override + public int getMaxNameThreshold(String domain) { + return 200; + } + } + + private static class MockServerConfigManager extends ServerConfigManager { + + @Override + public int getMaxTypeThreshold() { + return 100; + } + + @Override + public int getTpValueExpireMinute() { + return 1; + } + + @Override + public int getTypeNameLengthLimit() { + return 256; + } + } + + private static class MockServerFilterConfigManager extends ServerFilterConfigManager { + + @Override + public boolean discardTransaction(String type, String name) { + return false; + } + } + + private static class MockTpValueStatisticConfigManager extends TpValueStatisticConfigManager { + + @Override + public boolean shouldStatistic(String type, String domain) { + return false; + } + } + + private static class MockTransactionReportManager extends MockReportManager { + private final ReportDelegate m_delegate = new TransactionDelegate(); + + private TransactionReport m_report; + + @Override + public TransactionReport getHourlyReport(long startTime, String domain, boolean createIfNotExist) { + if (m_report == null) { + m_report = m_delegate.makeReport(domain, startTime, Constants.HOUR); + } + + return m_report; + } + + @Override + public void destory() { + } + } } diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportMergerTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportMergerTest.java index 326bb253b2..e068d1f9a2 100755 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportMergerTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportMergerTest.java @@ -20,7 +20,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; @@ -29,12 +28,12 @@ public class TransactionReportMergerTest { @Test public void testTransactionReportMerge() throws Exception { - String oldXml = Files.forIO().readFrom(getClass().getResourceAsStream("transaction_report_old.xml"), "utf-8"); - String newXml = Files.forIO().readFrom(getClass().getResourceAsStream("transaction_report_new.xml"), "utf-8"); + String oldXml = new String(getClass().getResourceAsStream("transaction_report_old.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + String newXml = new String(getClass().getResourceAsStream("transaction_report_new.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); TransactionReport reportOld = DefaultSaxParser.parse(oldXml); TransactionReport reportNew = DefaultSaxParser.parse(newXml); - String expected = Files.forIO() - .readFrom(getClass().getResourceAsStream("transaction_report_mergeResult.xml"), "utf-8"); + String expected = new String(getClass().getResourceAsStream("transaction_report_mergeResult.xml") + .readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); TransactionReport reportExpected = DefaultSaxParser.parse(expected); diff --git a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportTest.java b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportTest.java index c820b69f77..991c96d956 100644 --- a/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportTest.java +++ b/cat-consumer/src/test/java/com/dianping/cat/consumer/transaction/TransactionReportTest.java @@ -19,7 +19,6 @@ package com.dianping.cat.consumer.transaction; import org.junit.Test; -import org.unidal.helper.Files; import com.dianping.cat.consumer.TestHelper; import com.dianping.cat.consumer.transaction.model.entity.TransactionReport; @@ -28,7 +27,7 @@ public class TransactionReportTest { @Test public void testXml() throws Exception { - String source = Files.forIO().readFrom(getClass().getResourceAsStream("transaction_report.xml"), "utf-8"); + String source = new String(getClass().getResourceAsStream("transaction_report.xml").readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); TransactionReport report = DefaultSaxParser.parse(source); String expected = source; diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/business/business_analyzer.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/business/business_analyzer.xml deleted file mode 100644 index 4e29fa356a..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/business/business_analyzer.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/cross/CrossAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/cross/CrossAnalyzerTest.xml deleted file mode 100644 index f1d9d7214b..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/cross/CrossAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - cross - com.dianping.cat.consumer.cross.Configurator$MockCrossReportManager - - - com.dianping.cat.report.ReportDelegate - cross - - - - - com.dianping.cat.report.ReportDelegate - cross - com.dianping.cat.consumer.cross.Configurator$ExtendedCrossDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/dependency/DependencyAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/dependency/DependencyAnalyzerTest.xml deleted file mode 100644 index cddbd45c0d..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/dependency/DependencyAnalyzerTest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - dependency - com.dianping.cat.consumer.dependency.Configurator$MockDependencyReportManager - - - com.dianping.cat.report.ReportDelegate - dependency - - - - - com.dianping.cat.report.ReportDelegate - dependency - com.dianping.cat.consumer.dependency.Configurator$ExtendedDependencyDelegate - - - com.dianping.cat.dal.HostinfoService - com.dianping.cat.consumer.dependency.Configurator$ExtendedHostinfoService - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/event/EventAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/event/EventAnalyzerTest.xml deleted file mode 100644 index 5f10bc3355..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/event/EventAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - event - com.dianping.cat.consumer.event.Configurator$MockEventReportManager - - - com.dianping.cat.report.ReportDelegate - event - - - - - com.dianping.cat.report.ReportDelegate - event - com.dianping.cat.consumer.event.Configurator$ExtendedEventDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.xml deleted file mode 100644 index a99685df17..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/heartbeat/HeartbeatAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - heartbeat - com.dianping.cat.consumer.heartbeat.Configurator$MockHeartbeatReportManager - - - com.dianping.cat.report.ReportDelegate - heartbeat - - - - - com.dianping.cat.report.ReportDelegate - heartbeat - com.dianping.cat.consumer.heartbeat.Configurator$ExtendedHeartbeatDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.xml deleted file mode 100644 index 3a51c41900..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/matrix/MatrixAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - matrix - com.dianping.cat.consumer.matrix.Configurator$MockMatrixReportManager - - - com.dianping.cat.report.ReportDelegate - matrix - - - - - com.dianping.cat.report.ReportDelegate - matrix - com.dianping.cat.consumer.matrix.Configurator$ExtendedMatrixDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/CrossPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/CrossPerformanceTest.xml deleted file mode 100644 index b77761c565..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/CrossPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - cross - com.dianping.cat.consumer.performance.CrossConfigurator$MockCrossReportManager - - - com.dianping.cat.report.ReportDelegate - cross - - - - - com.dianping.cat.report.ReportDelegate - cross - com.dianping.cat.consumer.performance.CrossConfigurator$ExtendedCrossDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/DependencyPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/DependencyPerformanceTest.xml deleted file mode 100644 index 4d26979c93..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/DependencyPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - dependency - com.dianping.cat.consumer.performance.DependencyConfigurator$MockDependencyReportManager - - - com.dianping.cat.report.ReportDelegate - dependency - - - - - com.dianping.cat.report.ReportDelegate - dependency - com.dianping.cat.consumer.performance.DependencyConfigurator$ExtendedDependencyDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/EventPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/EventPerformanceTest.xml deleted file mode 100644 index 67f4973459..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/EventPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - event - com.dianping.cat.consumer.performance.EventConfigurator$MockEventReportManager - - - com.dianping.cat.report.ReportDelegate - event - - - - - com.dianping.cat.report.ReportDelegate - event - com.dianping.cat.consumer.performance.EventConfigurator$ExtendedEventDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/MatrixPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/MatrixPerformanceTest.xml deleted file mode 100644 index a8786e2a5f..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/MatrixPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - matrix - com.dianping.cat.consumer.performance.MatrixConfigurator$MockMatrixReportManager - - - com.dianping.cat.report.ReportDelegate - matrix - - - - - com.dianping.cat.report.ReportDelegate - matrix - com.dianping.cat.consumer.performance.MatrixConfigurator$ExtendedMatrixDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/ProblemPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/ProblemPerformanceTest.xml deleted file mode 100644 index c2c61b85ab..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/ProblemPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - problem - com.dianping.cat.consumer.performance.ProblemConfigurator$MockProblemReportManager - - - com.dianping.cat.report.ReportDelegate - problem - - - - - com.dianping.cat.report.ReportDelegate - problem - com.dianping.cat.consumer.performance.ProblemConfigurator$ExtendedProblemDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/TransactionPerformanceTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/TransactionPerformanceTest.xml deleted file mode 100644 index 72419f9356..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/performance/TransactionPerformanceTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - transaction - com.dianping.cat.consumer.performance.TransactionConfigurator$MockTransactionReportManager - - - com.dianping.cat.report.ReportDelegate - transaction - - - - - com.dianping.cat.report.ReportDelegate - transaction - com.dianping.cat.consumer.performance.TransactionConfigurator$ExtendedTransactionDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.xml deleted file mode 100644 index 360d0f09eb..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/problem/ProblemAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - problem - com.dianping.cat.consumer.problem.Configurator$MockProblemReportManager - - - com.dianping.cat.report.ReportDelegate - problem - - - - - com.dianping.cat.report.ReportDelegate - problem - com.dianping.cat.consumer.problem.Configurator$ExtendedProblemDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/state/StateAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/state/StateAnalyzerTest.xml deleted file mode 100644 index 092eb17448..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/state/StateAnalyzerTest.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - state - com.dianping.cat.consumer.state.Configurator$MockStateReportManager - - - com.dianping.cat.report.ReportDelegate - state - - - - - com.dianping.cat.report.ReportDelegate - state - com.dianping.cat.consumer.state.Configurator$ExtendedStateDelegate - - - com.dianping.cat.analysis.MessageAnalyzer - state - com.dianping.cat.consumer.state.StateAnalyzer - - 192.168.1.1 - - - - com.dianping.cat.report.ReportManager - state - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.statistic.ServerStatisticManager - - - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/top/TopAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/top/TopAnalyzerTest.xml deleted file mode 100644 index 3ea279d962..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/top/TopAnalyzerTest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - top - com.dianping.cat.consumer.top.Configurator$MockTopReportManager - per-lookup - - - com.dianping.cat.report.ReportDelegate - top - - - - - com.dianping.cat.report.ReportDelegate - top - com.dianping.cat.consumer.top.Configurator$ExtendedTopDelegate - - - diff --git a/cat-consumer/src/test/resources/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.xml b/cat-consumer/src/test/resources/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.xml deleted file mode 100644 index 1886061696..0000000000 --- a/cat-consumer/src/test/resources/com/dianping/cat/consumer/transaction/TransactionAnalyzerTest.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - com.dianping.cat.report.ReportManager - transaction - com.dianping.cat.consumer.transaction.Configurator$MockTransactionReportManager - - - com.dianping.cat.report.ReportDelegate - transaction - - - - - com.dianping.cat.report.ReportDelegate - transaction - com.dianping.cat.consumer.transaction.Configurator$ExtendedTransactionDelegate - - - diff --git a/cat-consumer/src/test/resources/logback-test.xml b/cat-consumer/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..31b2c13de8 --- /dev/null +++ b/cat-consumer/src/test/resources/logback-test.xml @@ -0,0 +1,11 @@ + + + + + [%d{HH:mm:ss.SSS}] [%-5level] [%logger{36}] %msg%n + + + + + + diff --git a/cat-core/pom.xml b/cat-core/pom.xml index 80229a3af0..b4ee3bdd9d 100644 --- a/cat-core/pom.xml +++ b/cat-core/pom.xml @@ -11,29 +11,57 @@ cat-core jar - - com.dianping.cat - cat-client - - - org.unidal.framework - foundation-service - - - org.unidal.framework - web-framework - - - org.xerial.snappy - snappy-java - - - org.unidal.framework - dal-jdbc - - - javax.servlet - servlet-api + + com.dianping.cat + cat-client + + + io.netty + netty-all + + + org.unidal.framework + web-framework + + + org.xerial.snappy + snappy-java + + + org.apache.commons + commons-lang3 + + + commons-io + commons-io + + + com.google.guava + guava + + + org.mybatis + mybatis + + + org.springframework + spring-context + + + org.mybatis + mybatis-spring + + + org.springframework + spring-tx + + + org.projectlombok + lombok + + + javax.servlet + servlet-api provided @@ -42,78 +70,22 @@ true provided - - org.unidal.framework - test-framework - test - - - com.google.code.gson - gson - + + ch.qos.logback + logback-classic + test + + + com.google.code.gson + gson + junit junit test - - - - org.unidal.maven.plugins - codegen-maven-plugin - - - generate data model - generate-sources - - dal-model - - - ${basedir}/src/main/resources/META-INF/dal/model/server-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/sample-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/business-report-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/atomic-message-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/tp-value-statistic-config-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/model/report-reload-config-manifest.xml, - - - - - generate dal jdbc model - generate-sources - - dal-jdbc - - - ${basedir}/src/main/resources/META-INF/dal/jdbc/report-manifest.xml, - ${basedir}/src/main/resources/META-INF/dal/jdbc/config-manifest.xml, - - - - - - - org.unidal.maven.plugins - plexus-maven-plugin - - - generate plexus component descriptor - process-classes - - plexus - - - com.dianping.cat.build.ComponentsConfigurator - - - - - - - + utf-8 diff --git a/cat-core/src/main/java/com/dianping/cat/CatCoreModule.java b/cat-core/src/main/java/com/dianping/cat/CatCoreModule.java deleted file mode 100644 index 788723c17a..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/CatCoreModule.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat; - -import org.unidal.initialization.AbstractModule; -import org.unidal.initialization.Module; -import org.unidal.initialization.ModuleContext; -import org.unidal.lookup.annotation.Named; - -import com.dianping.cat.report.server.ServersUpdaterManager; - -@Named(type = Module.class, value = CatCoreModule.ID) -public class CatCoreModule extends AbstractModule { - public static final String ID = "cat-core"; - - @Override - protected void execute(final ModuleContext ctx) throws Exception { - // bring up ServersUpdaterManager - ctx.lookup(ServersUpdaterManager.class); - } - - @Override - public Module[] getDependencies(ModuleContext ctx) { - return null; - } -} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/AbstractMessageAnalyzer.java b/cat-core/src/main/java/com/dianping/cat/analysis/AbstractMessageAnalyzer.java index 92b9539f42..8cbd48c1da 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/AbstractMessageAnalyzer.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/AbstractMessageAnalyzer.java @@ -20,31 +20,24 @@ import java.util.concurrent.atomic.AtomicBoolean; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; - import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.ReportManager; -public abstract class AbstractMessageAnalyzer extends ContainerHolder implements MessageAnalyzer { +public abstract class AbstractMessageAnalyzer implements MessageAnalyzer { public static final long MINUTE = 60 * 1000L; public static final long ONE_HOUR = 60 * 60 * 1000L; public static final long ONE_DAY = 24 * ONE_HOUR; - @Inject protected ServerConfigManager m_serverConfigManager; protected long m_startTime; protected long m_duration; - protected Logger m_logger; - protected int m_index; private long m_extraTime; @@ -92,7 +85,6 @@ public void analyze(MessageQueue queue) { @Override public void destroy() { - super.release(this); ReportManager manager = this.getReportManager(); if (manager != null) { @@ -156,6 +148,10 @@ public void setIndex(int index) { m_index = index; } + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; + } + public void shutdown() { m_active.set(false); } diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/ContainerMessageAnalyzerFactory.java b/cat-core/src/main/java/com/dianping/cat/analysis/ContainerMessageAnalyzerFactory.java new file mode 100644 index 0000000000..127087c47e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/analysis/ContainerMessageAnalyzerFactory.java @@ -0,0 +1,55 @@ +package com.dianping.cat.analysis; + +import java.util.Map; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class ContainerMessageAnalyzerFactory implements MessageAnalyzerFactory, ApplicationContextAware { + public static final String ANALYZER_BEAN_PREFIX = "messageAnalyzer."; + + private ApplicationContext m_context; + + @Override + public MessageAnalyzer createAnalyzer(String name) { + try { + return getContext().getBean(ANALYZER_BEAN_PREFIX + name, MessageAnalyzer.class); + } catch (BeansException e) { + throw new IllegalStateException("Unable to create message analyzer from Spring: " + name, e); + } + } + + @Override + public Map getAnalyzerMap() { + try { + Map beans = getContext().getBeansOfType(MessageAnalyzer.class); + Map analyzers = new java.util.LinkedHashMap(); + + for (Map.Entry entry : beans.entrySet()) { + String beanName = entry.getKey(); + + if (beanName.startsWith(ANALYZER_BEAN_PREFIX)) { + analyzers.put(beanName.substring(ANALYZER_BEAN_PREFIX.length()), entry.getValue()); + } + } + return analyzers; + } catch (BeansException e) { + throw new IllegalStateException("Unable to load message analyzer map from Spring.", e); + } + } + + private ApplicationContext getContext() { + if (m_context == null) { + throw new IllegalStateException("Spring application context is required for message analyzer factory."); + } + return m_context; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + m_context = applicationContext; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageAnalyzerManager.java b/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageAnalyzerManager.java index b20706c3e3..7a3cc5b21c 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageAnalyzerManager.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageAnalyzerManager.java @@ -25,33 +25,31 @@ 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.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; -@Named(type = MessageAnalyzerManager.class) -public class DefaultMessageAnalyzerManager extends ContainerHolder - implements MessageAnalyzerManager, Initializable, LogEnabled { +public class DefaultMessageAnalyzerManager + implements MessageAnalyzerManager { private static final long MINUTE = 60 * 1000L; - protected Logger m_logger; - private long m_duration = 60 * MINUTE; private long m_extraTime = 3 * MINUTE; private List m_analyzerNames; + private MessageAnalyzerFactory m_analyzerFactory; + + private ServerConfigManager m_configManager; + private final Map>> m_analyzers = new HashMap>>(); + private volatile boolean m_initialized; + @Override public List getAnalyzer(String name, long startTime) { + initialize(); + // remove last two hour analyzer try { Map> temp = m_analyzers.remove(startTime - m_duration * 2); @@ -89,7 +87,7 @@ public List getAnalyzer(String name, long startTime) { if (analyzers == null) { analyzers = new ArrayList(); - MessageAnalyzer analyzer = lookup(MessageAnalyzer.class, name); + MessageAnalyzer analyzer = createAnalyzer(name); analyzer.setIndex(0); analyzer.initialize(startTime, m_duration, m_extraTime); @@ -98,7 +96,7 @@ public List getAnalyzer(String name, long startTime) { int count = analyzer.getAnanlyzerCount(name); for (int i = 1; i < count; i++) { - MessageAnalyzer tempAnalyzer = lookup(MessageAnalyzer.class, name); + MessageAnalyzer tempAnalyzer = createAnalyzer(name); tempAnalyzer.setIndex(i); tempAnalyzer.initialize(startTime, m_duration, m_extraTime); @@ -114,12 +112,17 @@ public List getAnalyzer(String name, long startTime) { @Override public List getAnalyzerNames() { + initialize(); + return m_analyzerNames; } - @Override - public void initialize() throws InitializationException { - Map map = lookupMap(MessageAnalyzer.class); + public synchronized void initialize() { + if (m_initialized) { + return; + } + + Map map = getAnalyzerMap(); for (MessageAnalyzer analyzer : map.values()) { analyzer.destroy(); @@ -147,7 +150,7 @@ public int compare(String str1, String str2) { } }); - ServerConfigManager manager = lookup(ServerConfigManager.class); + ServerConfigManager manager = getConfigManager(); List disables = new ArrayList(); for (String name : m_analyzerNames) { @@ -159,10 +162,35 @@ public int compare(String str1, String str2) { for (String name : disables) { m_analyzerNames.remove(name); } + m_initialized = true; } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; + private MessageAnalyzer createAnalyzer(String name) { + if (m_analyzerFactory != null) { + return m_analyzerFactory.createAnalyzer(name); + } + throw new IllegalStateException("MessageAnalyzerFactory is required for DefaultMessageAnalyzerManager."); + } + + private ServerConfigManager getConfigManager() { + if (m_configManager != null) { + return m_configManager; + } + throw new IllegalStateException("ServerConfigManager is required for DefaultMessageAnalyzerManager."); + } + + private Map getAnalyzerMap() { + if (m_analyzerFactory != null) { + return m_analyzerFactory.getAnalyzerMap(); + } + throw new IllegalStateException("MessageAnalyzerFactory is required for DefaultMessageAnalyzerManager."); + } + + public void setAnalyzerFactory(MessageAnalyzerFactory analyzerFactory) { + m_analyzerFactory = analyzerFactory; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; } } diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageHandler.java b/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageHandler.java index 76beab3d86..c623fa424f 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageHandler.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/DefaultMessageHandler.java @@ -16,38 +16,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.dianping.cat.analysis; - -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +package com.dianping.cat.analysis; -import com.dianping.cat.message.spi.MessageTree; - -@Named(type = MessageHandler.class) -public class DefaultMessageHandler extends ContainerHolder implements MessageHandler, LogEnabled { - @Inject - private MessageConsumer m_consumer; - - private Logger m_logger; - - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - - @Override - public void handle(MessageTree tree) { - if (m_consumer == null) { - m_consumer = lookup(MessageConsumer.class); - } - - try { - m_consumer.consume(tree); - } catch (Throwable e) { - m_logger.error("Error when consuming message in " + m_consumer + "! tree: " + tree, e); - } - } -} +import org.slf4j.LoggerFactory; + +import com.dianping.cat.message.spi.MessageTree; + +public class DefaultMessageHandler implements MessageHandler { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(DefaultMessageHandler.class); + + private MessageConsumer m_consumer; + + @Override + public void handle(MessageTree tree) { + if (m_consumer == null) { + SLF4J_LOGGER.warn("Message consumer is not configured, drop message tree={}.", tree); + return; + } + + try { + m_consumer.consume(tree); + } catch (Throwable e) { + SLF4J_LOGGER.error("Error when consuming message, consumer={}, tree={}.", m_consumer, tree, e); + } + } + + public void setConsumer(MessageConsumer consumer) { + m_consumer = consumer; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/MessageAnalyzerFactory.java b/cat-core/src/main/java/com/dianping/cat/analysis/MessageAnalyzerFactory.java new file mode 100644 index 0000000000..288db07fe7 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/analysis/MessageAnalyzerFactory.java @@ -0,0 +1,10 @@ +package com.dianping.cat.analysis; + +import java.util.Map; + +public interface MessageAnalyzerFactory { + + public MessageAnalyzer createAnalyzer(String name); + + public Map getAnalyzerMap(); +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/Period.java b/cat-core/src/main/java/com/dianping/cat/analysis/Period.java index 7bb0ff628e..6884413e7b 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/Period.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/Period.java @@ -26,15 +26,16 @@ import java.util.Map; import java.util.Map.Entry; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Threads; -import org.unidal.lookup.annotation.Inject; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads; import com.dianping.cat.Cat; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.statistic.ServerStatisticManager; public class Period { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Period.class); + private static final int QUEUE_SIZE = 30000; private long m_startTime; @@ -43,22 +44,16 @@ public class Period { private Map> m_tasks; - @Inject private MessageAnalyzerManager m_analyzerManager; - @Inject private ServerStatisticManager m_serverStateManager; - @Inject - private Logger m_logger; - public Period(long startTime, long endTime, MessageAnalyzerManager analyzerManager, - ServerStatisticManager serverStateManager, Logger logger) { + ServerStatisticManager serverStateManager) { m_startTime = startTime; m_endTime = endTime; m_analyzerManager = analyzerManager; m_serverStateManager = serverStateManager; - m_logger = logger; List names = m_analyzerManager.getAnalyzerNames(); @@ -70,8 +65,6 @@ public Period(long startTime, long endTime, MessageAnalyzerManager analyzerManag MessageQueue queue = new DefaultMessageQueue(QUEUE_SIZE); PeriodTask task = new PeriodTask(analyzer, queue, startTime); - task.enableLogging(m_logger); - List analyzerTasks = m_tasks.get(name); if (analyzerTasks == null) { @@ -126,8 +119,7 @@ public void finish() { Date startDate = new Date(m_startTime); Date endDate = new Date(m_endTime - 1); - m_logger.info(String - .format("Finishing %s tasks in period [%s, %s]", m_tasks.size(), df.format(startDate), df.format(endDate))); + LOGGER.info("Finishing {} tasks in period [{}, {}]", m_tasks.size(), df.format(startDate), df.format(endDate)); try { for (Entry> tasks : m_tasks.entrySet()) { @@ -138,8 +130,7 @@ public void finish() { } catch (Throwable e) { Cat.logError(e); } finally { - m_logger.info(String - .format("Finished %s tasks in period [%s, %s]", m_tasks.size(), df.format(startDate), df.format(endDate))); + LOGGER.info("Finished {} tasks in period [{}, {}]", m_tasks.size(), df.format(startDate), df.format(endDate)); } } @@ -178,8 +169,8 @@ public boolean isIn(long timestamp) { public void start() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - m_logger.info(String.format("Starting %s tasks in period [%s, %s]", m_tasks.size(), df.format(new Date(m_startTime)), - df.format(new Date(m_endTime - 1)))); + LOGGER.info("Starting {} tasks in period [{}, {}]", m_tasks.size(), df.format(new Date(m_startTime)), + df.format(new Date(m_endTime - 1))); for (Entry> tasks : m_tasks.entrySet()) { List taskList = tasks.getValue(); diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/PeriodManager.java b/cat-core/src/main/java/com/dianping/cat/analysis/PeriodManager.java index 39bc10873d..4835d2323e 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/PeriodManager.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/PeriodManager.java @@ -21,10 +21,8 @@ import java.util.ArrayList; import java.util.List; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Threads; -import org.unidal.helper.Threads.Task; -import org.unidal.lookup.annotation.Inject; +import com.dianping.cat.support.Threads; +import com.dianping.cat.support.Threads.Task; import com.dianping.cat.Cat; import com.dianping.cat.statistic.ServerStatisticManager; @@ -38,22 +36,15 @@ public class PeriodManager implements Task { private boolean m_active; - @Inject private MessageAnalyzerManager m_analyzerManager; - @Inject private ServerStatisticManager m_serverStateManager; - @Inject - private Logger m_logger; - - public PeriodManager(long duration, MessageAnalyzerManager analyzerManager, ServerStatisticManager serverStateManager, - Logger logger) { + public PeriodManager(long duration, MessageAnalyzerManager analyzerManager, ServerStatisticManager serverStateManager) { m_strategy = new PeriodStrategy(duration, EXTRATIME, EXTRATIME); m_active = true; m_analyzerManager = analyzerManager; m_serverStateManager = serverStateManager; - m_logger = logger; } private void endPeriod(long startTime) { @@ -123,7 +114,7 @@ public void shutdown() { private void startPeriod(long startTime) { long endTime = startTime + m_strategy.getDuration(); - Period period = new Period(startTime, endTime, m_analyzerManager, m_serverStateManager, m_logger); + Period period = new Period(startTime, endTime, m_analyzerManager, m_serverStateManager); m_periods.add(period); period.start(); @@ -151,4 +142,4 @@ public void run() { public void shutdown() { } } -} \ No newline at end of file +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/PeriodTask.java b/cat-core/src/main/java/com/dianping/cat/analysis/PeriodTask.java index 16a81db954..c6d09bb443 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/PeriodTask.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/PeriodTask.java @@ -22,15 +22,15 @@ import java.util.Calendar; import java.util.Date; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Threads.Task; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads.Task; import com.dianping.cat.Cat; import com.dianping.cat.CatConstants; import com.dianping.cat.message.spi.MessageTree; -public class PeriodTask implements Task, LogEnabled { +public class PeriodTask implements Task { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(PeriodTask.class); private MessageAnalyzer m_analyzer; @@ -40,8 +40,6 @@ public class PeriodTask implements Task, LogEnabled { private int m_queueOverflow; - private Logger m_logger; - private int m_index; public PeriodTask(MessageAnalyzer analyzer, MessageQueue queue, long startTime) { @@ -54,11 +52,6 @@ public void setIndex(int index) { m_index = index; } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - public boolean enqueue(MessageTree tree) { if (m_analyzer.isEligable(tree)) { boolean result = m_queue.offer(tree); @@ -69,9 +62,8 @@ public boolean enqueue(MessageTree tree) { if (m_queueOverflow % (10 * CatConstants.ERROR_COUNT) == 0) { String date = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(m_analyzer.getStartTime())); - m_logger - .warn(m_analyzer.getClass().getSimpleName() + " queue overflow number " + m_queueOverflow + " analyzer time:" - + date); + LOGGER.warn("{} queue overflow number {} analyzer time:{}", m_analyzer.getClass().getSimpleName(), + m_queueOverflow, date); } } return result; @@ -116,4 +108,4 @@ public void shutdown() { ((AbstractMessageAnalyzer) m_analyzer).shutdown(); } } -} \ No newline at end of file +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/RealtimeConsumer.java b/cat-core/src/main/java/com/dianping/cat/analysis/RealtimeConsumer.java index dd67c7a181..203205f271 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/RealtimeConsumer.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/RealtimeConsumer.java @@ -20,14 +20,8 @@ import java.util.List; -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.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads; import com.dianping.cat.Cat; import com.dianping.cat.message.Message; @@ -35,47 +29,56 @@ import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.statistic.ServerStatisticManager; -@Named(type = MessageConsumer.class) -public class RealtimeConsumer extends ContainerHolder implements MessageConsumer, Initializable, LogEnabled { +public class RealtimeConsumer implements MessageConsumer { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(RealtimeConsumer.class); + public static final long MINUTE = 60 * 1000L; public static final long HOUR = 60 * MINUTE; - @Inject private MessageAnalyzerManager m_analyzerManager; - @Inject private ServerStatisticManager m_serverStateManager; private PeriodManager m_periodManager; - private Logger m_logger; + private volatile boolean m_initialized; @Override public void consume(MessageTree tree) { + initialize(); + long timestamp = getTimestamp(tree); Period period = m_periodManager.findPeriod(timestamp); if (period != null) { period.distribute(tree); } else { + SLF4J_LOGGER.warn("No realtime period found for message tree, timestamp={}, tree={}.", timestamp, tree); m_serverStateManager.addNetworkTimeError(1); } } public void doCheckpoint() { - m_logger.info("starting do checkpoint."); + initialize(); + + info("starting do checkpoint."); Transaction t = Cat.newTransaction("Checkpoint", getClass().getSimpleName()); try { long currentStartTime = getCurrentStartTime(); Period period = m_periodManager.findPeriod(currentStartTime); - for (MessageAnalyzer analyzer : period.getAnalyzers()) { - try { - analyzer.doCheckpoint(false); - } catch (Exception e) { - Cat.logError(e); + if (period == null) { + SLF4J_LOGGER.warn("No current realtime period found when doing checkpoint, startTime={}.", currentStartTime); + } else { + for (MessageAnalyzer analyzer : period.getAnalyzers()) { + try { + analyzer.doCheckpoint(false); + } catch (Exception e) { + Cat.logError(e); + SLF4J_LOGGER.error("Failed to checkpoint realtime analyzer, analyzer={}.", analyzer, e); + } } } @@ -88,20 +91,18 @@ public void doCheckpoint() { t.setStatus(Message.SUCCESS); } catch (RuntimeException e) { Cat.logError(e); + SLF4J_LOGGER.error("Failed to do realtime checkpoint.", e); t.setStatus(e); } finally { t.complete(); } - m_logger.info("end do checkpoint."); - } - - @Override - public void enableLogging(Logger logger) { - m_logger = logger; + info("end do checkpoint."); } @Override public List getCurrentAnalyzer(String name) { + initialize(); + long currentStartTime = getCurrentStartTime(); Period period = m_periodManager.findPeriod(currentStartTime); @@ -120,6 +121,8 @@ private long getCurrentStartTime() { @Override public List getLastAnalyzer(String name) { + initialize(); + long lastStartTime = getCurrentStartTime() - HOUR; Period period = m_periodManager.findPeriod(lastStartTime); @@ -138,12 +141,36 @@ private long getTimestamp(MessageTree tree) { } } - @Override - public void initialize() throws InitializationException { - m_periodManager = new PeriodManager(HOUR, m_analyzerManager, m_serverStateManager, m_logger); + public synchronized void initialize() { + if (m_initialized) { + return; + } + + if (m_analyzerManager == null) { + throw new IllegalStateException("MessageAnalyzerManager is required for RealtimeConsumer."); + } + if (m_serverStateManager == null) { + throw new IllegalStateException("ServerStatisticManager is required for RealtimeConsumer."); + } + + m_periodManager = new PeriodManager(HOUR, m_analyzerManager, m_serverStateManager); m_periodManager.init(); Threads.forGroup("Cat").start(m_periodManager); + m_initialized = true; + SLF4J_LOGGER.info("Initialized realtime consumer."); + } + + private void info(String message) { + SLF4J_LOGGER.info(message); + } + + public void setAnalyzerManager(MessageAnalyzerManager analyzerManager) { + m_analyzerManager = analyzerManager; + } + + public void setServerStateManager(ServerStatisticManager serverStateManager) { + m_serverStateManager = serverStateManager; } -} \ No newline at end of file +} diff --git a/cat-core/src/main/java/com/dianping/cat/analysis/TcpSocketReceiver.java b/cat-core/src/main/java/com/dianping/cat/analysis/TcpSocketReceiver.java index d3bc7715e3..67799c9bf9 100644 --- a/cat-core/src/main/java/com/dianping/cat/analysis/TcpSocketReceiver.java +++ b/cat-core/src/main/java/com/dianping/cat/analysis/TcpSocketReceiver.java @@ -20,10 +20,7 @@ import java.util.List; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.LoggerFactory; import com.dianping.cat.CatConstants; import com.dianping.cat.config.server.ServerConfigManager; @@ -48,16 +45,13 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.ByteToMessageDecoder; -@Named(type = TcpSocketReceiver.class) -public final class TcpSocketReceiver implements LogEnabled { +public final class TcpSocketReceiver { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(TcpSocketReceiver.class); - @Inject protected ServerConfigManager m_serverConfigManager; - @Inject private MessageHandler m_handler; - @Inject private ServerStatisticManager m_serverStateManager; private ChannelFuture m_future; @@ -66,27 +60,26 @@ public final class TcpSocketReceiver implements LogEnabled { private EventLoopGroup m_workerGroup; - private Logger m_logger; - - private final int m_port = 2280; // default port number from phone, C:2, A:2, T:8 + private final int m_port = Integer.getInteger("cat.tcp.port", 2280); // default port number from phone, C:2, A:2, T:8 public synchronized void destory() { try { - m_logger.info("start shutdown socket, port " + m_port); - m_future.channel().closeFuture(); - m_bossGroup.shutdownGracefully(); - m_workerGroup.shutdownGracefully(); - m_logger.info("shutdown socket success"); + info("start shutdown socket, port " + m_port); + if (m_future != null) { + m_future.channel().closeFuture(); + } + if (m_bossGroup != null) { + m_bossGroup.shutdownGracefully(); + } + if (m_workerGroup != null) { + m_workerGroup.shutdownGracefully(); + } + info("shutdown socket success"); } catch (Exception e) { - m_logger.warn(e.getMessage(), e); + warn(e.getMessage(), e); } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - protected boolean getOSMatches(String osNamePrefix) { String os = System.getProperty("os.name"); @@ -98,9 +91,15 @@ protected boolean getOSMatches(String osNamePrefix) { public void init() { try { + if (m_handler == null) { + throw new IllegalStateException("MessageHandler is required for TcpSocketReceiver."); + } + if (m_serverStateManager == null) { + throw new IllegalStateException("ServerStatisticManager is required for TcpSocketReceiver."); + } startServer(m_port); } catch (Exception e) { - m_logger.error(e.getMessage(), e); + error(e.getMessage(), e); } } @@ -130,12 +129,36 @@ protected void initChannel(SocketChannel ch) throws Exception { try { m_future = bootstrap.bind(port).sync(); - m_logger.info("start netty server!"); + info("start netty server!"); } catch (Exception e) { - m_logger.error("Started Netty Server Failed:" + port, e); + error("Started Netty Server Failed:" + port, e); } } + public void setHandler(MessageHandler handler) { + m_handler = handler; + } + + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; + } + + public void setServerStateManager(ServerStatisticManager serverStateManager) { + m_serverStateManager = serverStateManager; + } + + private void error(String message, Throwable cause) { + SLF4J_LOGGER.error(message, cause); + } + + private void info(String message) { + SLF4J_LOGGER.info(message); + } + + private void warn(String message, Throwable cause) { + SLF4J_LOGGER.warn(message, cause); + } + private class MessageDecoder extends ByteToMessageDecoder { private long m_processCount; @@ -180,9 +203,9 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List ou } } catch (Exception e) { m_serverStateManager.addMessageTotalLoss(1); - m_logger.error(e.getMessage(), e); + error(e.getMessage(), e); } } } -} \ No newline at end of file +} diff --git a/cat-core/src/main/java/com/dianping/cat/app/AppDataField.java b/cat-core/src/main/java/com/dianping/cat/app/AppDataField.java index 8741d26bdf..aa1478dc05 100644 --- a/cat-core/src/main/java/com/dianping/cat/app/AppDataField.java +++ b/cat-core/src/main/java/com/dianping/cat/app/AppDataField.java @@ -18,8 +18,6 @@ */ package com.dianping.cat.app; -import org.unidal.lookup.util.StringUtils; - public enum AppDataField { OPERATOR("operator", "运营商"), @@ -47,7 +45,7 @@ public enum AppDataField { } public static AppDataField getByName(String name, AppDataField defaultField) { - if (StringUtils.isNotEmpty(name)) { + if (isNotEmpty(name)) { for (AppDataField field : AppDataField.values()) { if (field.getName().equals(name)) { return field; @@ -58,7 +56,7 @@ public static AppDataField getByName(String name, AppDataField defaultField) { } public static AppDataField getByTitle(String title) { - if (StringUtils.isNotEmpty(title)) { + if (isNotEmpty(title)) { for (AppDataField field : AppDataField.values()) { if (field.getTitle().equals(title)) { return field; @@ -68,6 +66,10 @@ public static AppDataField getByTitle(String title) { return null; } + private static boolean isNotEmpty(String value) { + return value != null && value.length() > 0; + } + public String getName() { return m_name; } diff --git a/cat-core/src/main/java/com/dianping/cat/build/CatCoreDatabaseConfigurator.java b/cat-core/src/main/java/com/dianping/cat/build/CatCoreDatabaseConfigurator.java deleted file mode 100644 index 89a6faca6a..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/build/CatCoreDatabaseConfigurator.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.build; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.dal.jdbc.configuration.AbstractJdbcResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -final class CatCoreDatabaseConfigurator extends AbstractJdbcResourceConfigurator { - @Override - public List defineComponents() { - List all = new ArrayList(); - - defineSimpleTableProviderComponents(all, "cat", com.dianping.cat.core.config._INDEX.getEntityClasses()); - defineDaoComponents(all, com.dianping.cat.core.config._INDEX.getDaoClasses()); - - defineSimpleTableProviderComponents(all, "cat", com.dianping.cat.core.dal._INDEX.getEntityClasses()); - defineDaoComponents(all, com.dianping.cat.core.dal._INDEX.getDaoClasses()); - - return all; - } -} diff --git a/cat-core/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java b/cat-core/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java deleted file mode 100644 index 267fcedac3..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/build/CatDatabaseConfigurator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.build; - -import java.util.ArrayList; -import java.util.List; - -import org.unidal.dal.jdbc.configuration.AbstractJdbcResourceConfigurator; -import org.unidal.lookup.configuration.Component; - -public final class CatDatabaseConfigurator extends AbstractJdbcResourceConfigurator { - @Override - public List defineComponents() { - List all = new ArrayList(); - - // all.add(defineJdbcDataSourceComponent("cat", "com.mysql.jdbc.Driver", "jdbc:mysql://127.0.0.1:3306/cat", "root", "***", "")); - - defineSimpleTableProviderComponents(all, "cat", com.dianping.cat.core.dal._INDEX.getEntityClasses()); - defineDaoComponents(all, com.dianping.cat.core.dal._INDEX.getDaoClasses()); - - defineSimpleTableProviderComponents(all, "cat", com.dianping.cat.core.config._INDEX.getEntityClasses()); - defineDaoComponents(all, com.dianping.cat.core.config._INDEX.getDaoClasses()); - - return all; - } -} diff --git a/cat-core/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java b/cat-core/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java deleted file mode 100644 index 6f83d87e6a..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/build/ComponentsConfigurator.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.build; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.unidal.dal.jdbc.configuration.AbstractJdbcResourceConfigurator; -import org.unidal.lookup.configuration.Component; -import com.dianping.cat.CatConstants; -import com.dianping.cat.CatCoreModule; -import com.dianping.cat.analysis.DefaultMessageAnalyzerManager; -import com.dianping.cat.analysis.DefaultMessageHandler; -import com.dianping.cat.analysis.RealtimeConsumer; -import com.dianping.cat.analysis.TcpSocketReceiver; -import com.dianping.cat.config.AtomicMessageConfigManager; -import com.dianping.cat.config.ReportReloadConfigManager; -import com.dianping.cat.config.business.BusinessConfigManager; -import com.dianping.cat.config.content.LocalResourceContentFetcher; -import com.dianping.cat.config.sample.SampleConfigManager; -import com.dianping.cat.config.server.ServerConfigManager; -import com.dianping.cat.config.server.ServerFilterConfigManager; -import com.dianping.cat.config.transaction.TpValueStatisticConfigManager; -import com.dianping.cat.message.DefaultPathBuilder; -import com.dianping.cat.message.storage.LocalMessageBucket; -import com.dianping.cat.report.DefaultReportBucketManager; -import com.dianping.cat.report.DomainValidator; -import com.dianping.cat.report.LocalReportBucket; -import com.dianping.cat.report.server.RemoteServersManager; -import com.dianping.cat.report.server.ServersUpdaterManager; -import com.dianping.cat.service.HostinfoService; -import com.dianping.cat.service.IpService; -import com.dianping.cat.service.IpService2; -import com.dianping.cat.statistic.ServerStatisticManager; -import com.dianping.cat.task.TaskManager; - -public class ComponentsConfigurator extends AbstractJdbcResourceConfigurator { - public static void main(String[] args) { - generatePlexusComponentsXmlFile(new ComponentsConfigurator()); - } - - @Override - public List defineComponents() { - List all = new ArrayList(); - - all.add(A(RealtimeConsumer.class)); - - all.add(A(ServerConfigManager.class)); - all.add(A(HostinfoService.class)); - all.add(A(IpService.class)); - all.add(A(IpService2.class)); - all.add(A(TaskManager.class)); - all.add(A(ServerStatisticManager.class)); - all.add(A(DomainValidator.class)); - all.add(A(LocalResourceContentFetcher.class)); - all.add(A(ServerFilterConfigManager.class)); - - all.add(A(DefaultPathBuilder.class)); - - all.add(A(DefaultMessageAnalyzerManager.class)); - - all.add(A(TcpSocketReceiver.class)); - - all.add(A(DefaultMessageHandler.class)); - - all.add(A(SampleConfigManager.class)); - all.add(A(BusinessConfigManager.class)); - all.add(A(ReportReloadConfigManager.class)); - - all.add(A(CatCoreModule.class)); - - all.addAll(defineStorageComponents()); - - all.add(A(RemoteServersManager.class)); - all.add(A(ServersUpdaterManager.class)); - - all.add(A(TpValueStatisticConfigManager.class)); - all.add(A(AtomicMessageConfigManager.class)); - - all.add(defineJdbcDataSourceConfigurationManagerComponent("datasources.xml") - .config(E("baseDirRef").value("CAT_HOME")) - .config(E("defaultBaseDir").value(CatConstants.CAT_HOME_DEFAULT_DIR))); - - all.addAll(new CatCoreDatabaseConfigurator().defineComponents()); - all.addAll(new CatDatabaseConfigurator().defineComponents()); - - return all; - } - - private Collection defineStorageComponents() { - List all = new ArrayList(); - - all.add(A(DefaultReportBucketManager.class)); - all.add(A(LocalReportBucket.class)); - all.add(A(LocalMessageBucket.class)); - - return all; - } - -} diff --git a/cat-core/src/main/java/com/dianping/cat/config/AtomicMessageConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/AtomicMessageConfigManager.java index 8a07f1956a..58ac0c1063 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/AtomicMessageConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/AtomicMessageConfigManager.java @@ -18,11 +18,9 @@ */ package com.dianping.cat.config; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.content.ContentFetcher; @@ -31,43 +29,56 @@ import com.dianping.cat.configuration.message.entity.Property; import com.dianping.cat.configuration.message.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; -@Named -public class AtomicMessageConfigManager implements Initializable { +public class AtomicMessageConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AtomicMessageConfigManager.class); private static final String CONFIG_NAME = "atomic-message-config"; private static final String DEFAULT_DOMAIN = "default"; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private long m_modifyTime; private AtomicMessageConfig m_config; + private volatile boolean m_initialized; + public AtomicMessageConfig getConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + LOGGER.info("Loaded atomic message config from repository, configId={}, modifyTime={}.", m_configId, + m_modifyTime); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Atomic message config is missing in repository, loading default content from fetcher.", e); + try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -77,14 +88,18 @@ public void initialize() throws InitializationException { m_configDao.insert(config); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); + LOGGER.info("Initialized atomic message config from default content, configId={}.", m_configId); } catch (Exception ex) { + LOGGER.error("Unable to initialize atomic message config from default content.", ex); Cat.logError(ex); } } catch (Exception e) { + LOGGER.error("Unable to load atomic message config from repository.", e); Cat.logError(e); } if (m_config == null) { m_config = new AtomicMessageConfig(); + LOGGER.warn("Atomic message config is empty after initialization, using a new empty config."); } TimerSyncTask.getInstance().register(new TimerSyncTask.SyncHandler() { @@ -99,20 +114,27 @@ public void handle() throws Exception { refreshConfig(); } }); + m_initialized = true; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse atomic message config xml for insert. xmlLength={}.", + xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } } public String queryAtomicMatchTypes(String domain) { + ensureInitialized(); + Domain d = m_config.findDomain(domain); if (d == null) { @@ -127,6 +149,8 @@ public String queryAtomicMatchTypes(String domain) { } public String queryAtomicStartTypes(String domain) { + ensureInitialized(); + Domain d = m_config.findDomain(domain); if (d == null) { @@ -141,6 +165,8 @@ public String queryAtomicStartTypes(String domain) { } public String queryMaxMetricTagValues(String domain) { + ensureInitialized(); + Domain d = m_config.findDomain(domain); if (d == null) { @@ -158,7 +184,17 @@ public String queryMaxMetricTagValues(String domain) { return "10000"; } + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + public int getPropertyValue(String domain, String propertyName, int defaultValue) { + ensureInitialized(); + int result = defaultValue; Domain d = m_config.findDomain(domain); @@ -173,7 +209,8 @@ public int getPropertyValue(String domain, String propertyName, int defaultValue try { result = Integer.parseInt(property.getValue()); } catch (Exception e) { - //ignore + LOGGER.warn("Unable to parse atomic message property, domain={}, propertyName={}, value={}; " + + "using defaultValue={}.", domain, propertyName, property.getValue(), defaultValue, e); } } } @@ -193,7 +230,7 @@ public int getMaxBusinessItemCount(String domain) { } private void refreshConfig() throws Exception { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -203,6 +240,7 @@ private void refreshConfig() throws Exception { m_config = messageConfig; m_modifyTime = modifyTime; + LOGGER.info("Refreshed atomic message config, configId={}, modifyTime={}.", m_configId, m_modifyTime); } } } @@ -216,8 +254,10 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored atomic message config, configId={}.", m_configId); } catch (Exception e) { + LOGGER.error("Unable to store atomic message config, configId={}.", m_configId, e); Cat.logError(e); return false; } @@ -225,4 +265,4 @@ private boolean storeConfig() { return true; } -} \ No newline at end of file +} diff --git a/cat-core/src/main/java/com/dianping/cat/config/ReportReloadConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/ReportReloadConfigManager.java index aa4b46d6a9..62b2fb874c 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/ReportReloadConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/ReportReloadConfigManager.java @@ -24,11 +24,9 @@ import java.util.Date; import java.util.List; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.content.ContentFetcher; @@ -37,44 +35,57 @@ import com.dianping.cat.configuration.reload.entity.ReportType; import com.dianping.cat.configuration.reload.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class ReportReloadConfigManager implements Initializable { +public class ReportReloadConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(ReportReloadConfigManager.class); private static final String CONFIG_NAME = "report-reload-config"; private static final String DEFAULT = "default"; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private long m_modifyTime; private ReportReloadConfig m_config; + private volatile boolean m_initialized; + public ReportReloadConfig getConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + LOGGER.info("Loaded report reload config from repository, configId={}, modifyTime={}.", m_configId, + m_modifyTime); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Report reload config is missing in repository, loading default content from fetcher.", e); + try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -84,14 +95,18 @@ public void initialize() throws InitializationException { m_configDao.insert(config); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); + LOGGER.info("Initialized report reload config from default content, configId={}.", m_configId); } catch (Exception ex) { + LOGGER.error("Unable to initialize report reload config from default content.", ex); Cat.logError(ex); } } catch (Exception e) { + LOGGER.error("Unable to load report reload config from repository.", e); Cat.logError(e); } if (m_config == null) { m_config = new ReportReloadConfig(); + LOGGER.warn("Report reload config is empty after initialization, using a new empty config."); } TimerSyncTask.getInstance().register(new SyncHandler() { @@ -106,20 +121,27 @@ public void handle() throws Exception { refreshConfig(); } }); + m_initialized = true; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse report reload config xml for insert. xmlLength={}.", + xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } } public List queryByReportType(String type) { + ensureInitialized(); + ReportType reportType = m_config.findReportType(type); ArrayList results = new ArrayList(); @@ -137,6 +159,7 @@ public List queryByReportType(String type) { results.add(period); } catch (ParseException e) { + LOGGER.warn("Unable to parse report reload period, type={}, periodId={}.", type, rp.getId(), e); Cat.logError(e); } } @@ -145,8 +168,16 @@ public List queryByReportType(String type) { return results; } + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + private void refreshConfig() throws Exception { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -156,6 +187,7 @@ private void refreshConfig() throws Exception { m_config = reportReloadConfig; m_modifyTime = modifyTime; + LOGGER.info("Refreshed report reload config, configId={}, modifyTime={}.", m_configId, m_modifyTime); } } } @@ -169,8 +201,10 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored report reload config, configId={}.", m_configId); } catch (Exception e) { + LOGGER.error("Unable to store report reload config, configId={}.", m_configId, e); Cat.logError(e); return false; } diff --git a/cat-core/src/main/java/com/dianping/cat/config/business/BusinessConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/business/BusinessConfigManager.java index 173e9b2e29..56d3d6af2f 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/business/BusinessConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/business/BusinessConfigManager.java @@ -25,13 +25,9 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; @@ -39,18 +35,18 @@ import com.dianping.cat.configuration.business.entity.BusinessReportConfig; import com.dianping.cat.configuration.business.transform.DefaultSaxParser; import com.dianping.cat.core.config.BusinessConfig; -import com.dianping.cat.core.config.BusinessConfigDao; -import com.dianping.cat.core.config.BusinessConfigEntity; +import com.dianping.cat.mybatis.mapper.BusinessConfigRepository; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class BusinessConfigManager extends ContainerHolder implements Initializable { +public class BusinessConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessConfigManager.class); public final static String BASE_CONFIG = "base"; - @Inject - private BusinessConfigDao m_configDao; + private BusinessConfigRepository m_configDao; + + private ServerConfigManager m_serverConfigManager; private Map> m_domains = new ConcurrentHashMap>(); @@ -58,6 +54,8 @@ public class BusinessConfigManager extends ContainerHolder implements Initializa private boolean m_alertMachine; + private volatile boolean m_initialized; + private BusinessItemConfig buildBusinessItemConfig(String key, ConfigItem item) { BusinessItemConfig config = new BusinessItemConfig(); @@ -71,20 +69,23 @@ private BusinessItemConfig buildBusinessItemConfig(String key, ConfigItem item) } public boolean deleteBusinessItem(String domain, String key) { + ensureInitialized(); + try { - BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain, BusinessConfigEntity.READSET_FULL); + BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain); BusinessReportConfig businessReportConfig = DefaultSaxParser.parse(config.getContent()); businessReportConfig.removeBusinessItemConfig(key); config.setContent(businessReportConfig.toString()); config.setUpdatetime(new Date()); - m_configDao.updateByPK(config, BusinessConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); Set itemIds = m_domains.get(domain); itemIds.remove(key); cacheConfigs(businessReportConfig, domain); } catch (Exception e) { + LOGGER.error("Unable to delete business item config, domain={}, key={}.", domain, key, e); Cat.logError(e); return false; } @@ -92,17 +93,20 @@ public boolean deleteBusinessItem(String domain, String key) { } public boolean deleteCustomItem(String domain, String key) { + ensureInitialized(); + try { - BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain, BusinessConfigEntity.READSET_FULL); + BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain); BusinessReportConfig businessReportConfig = DefaultSaxParser.parse(config.getContent()); businessReportConfig.removeCustomConfig(key); config.setContent(businessReportConfig.toString()); config.setUpdatetime(new Date()); - m_configDao.updateByPK(config, BusinessConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); cacheConfigs(businessReportConfig, domain); } catch (Exception e) { + LOGGER.error("Unable to delete business custom config, domain={}, key={}.", domain, key, e); Cat.logError(e); return false; } @@ -110,10 +114,26 @@ public boolean deleteCustomItem(String domain, String key) { return true; } - @Override - public void initialize() throws InitializationException { - ServerConfigManager serverConfigManager = lookup(ServerConfigManager.class); - m_alertMachine = serverConfigManager.isAlertMachine(); + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + + if (m_serverConfigManager == null) { + throw new IllegalStateException("ServerConfigManager is required for BusinessConfigManager."); + } + if (m_configDao == null) { + throw new IllegalStateException("BusinessConfigRepository is required for BusinessConfigManager."); + } + + m_alertMachine = m_serverConfigManager.isAlertMachine(); + LOGGER.info("Initializing business config manager, alertMachine={}.", m_alertMachine); loadData(); @@ -129,11 +149,20 @@ public String getName() { return BASE_CONFIG; } }); + m_initialized = true; + } + + public void setConfigDao(BusinessConfigRepository configDao) { + m_configDao = configDao; + } + + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; } private void loadData() { try { - List configs = m_configDao.findByName(BASE_CONFIG, BusinessConfigEntity.READSET_FULL); + List configs = m_configDao.findByName(BASE_CONFIG); Map> domains = new ConcurrentHashMap>(); for (BusinessConfig config : configs) { @@ -145,12 +174,16 @@ private void loadData() { domains.put(domain, itemIds); cacheConfigs(businessReportConfig, domain); } catch (Exception e) { + LOGGER.error("Unable to parse business config, configId={}, domain={}.", config.getId(), + config.getDomain(), e); Cat.logError(e); } } m_domains = domains; + LOGGER.info("Loaded business configs, configCount={}, domainCount={}.", configs.size(), m_domains.size()); } catch (Exception e) { + LOGGER.error("Unable to load business configs.", e); Cat.logError(e); } } @@ -162,6 +195,8 @@ private void cacheConfigs(BusinessReportConfig businessReportConfig, String doma } public boolean insertBusinessConfigIfNotExist(String domain, String key, ConfigItem item) { + ensureInitialized(); + try { if (!m_domains.containsKey(domain)) { BusinessReportConfig config = new BusinessReportConfig(); @@ -181,45 +216,51 @@ public boolean insertBusinessConfigIfNotExist(String domain, String key, ConfigI itemIds.add(key); m_domains.put(domain, itemIds); cacheConfigs(config, domain); + LOGGER.info("Inserted new business config, domain={}, key={}.", domain, key); } else { Set itemIds = m_domains.get(domain); if (!itemIds.contains(key)) { BusinessConfig businessConfig = m_configDao - .findByNameDomain(BASE_CONFIG, domain, BusinessConfigEntity.READSET_FULL); + .findByNameDomain(BASE_CONFIG, domain); BusinessReportConfig config = DefaultSaxParser.parse(businessConfig.getContent()); BusinessItemConfig businessItemConfig = buildBusinessItemConfig(key, item); config.addBusinessItemConfig(businessItemConfig); businessConfig.setContent(config.toString()); - m_configDao.updateByPK(businessConfig, BusinessConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(businessConfig); itemIds.add(key); cacheConfigs(config, domain); + LOGGER.info("Inserted business item config, domain={}, key={}.", domain, key); } } return true; } catch (Exception e) { + LOGGER.error("Unable to insert business config if not exists, domain={}, key={}.", domain, key, e); Cat.logError(e); } return false; } public BusinessReportConfig queryConfigByDomain(String domain) { + ensureInitialized(); + BusinessReportConfig businessReportConfig = null; try { if (m_alertMachine) { businessReportConfig = m_configs.get(domain); } else { - BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain, BusinessConfigEntity.READSET_FULL); + BusinessConfig config = m_configDao.findByNameDomain(BASE_CONFIG, domain); businessReportConfig = DefaultSaxParser.parse(config.getContent()); } - } catch (DalNotFoundException notFound) { - // Ignore + } catch (EmptyResultDataAccessException notFound) { + LOGGER.warn("Business config is missing, domain={}; returning empty config.", domain, notFound); } catch (Exception e) { + LOGGER.error("Unable to query business config by domain={}.", domain, e); Cat.logError(e); } @@ -230,6 +271,8 @@ public BusinessReportConfig queryConfigByDomain(String domain) { } public boolean updateConfigByDomain(BusinessReportConfig config) { + ensureInitialized(); + BusinessConfig proto = m_configDao.createLocal(); String domain = config.getId(); @@ -238,10 +281,12 @@ public boolean updateConfigByDomain(BusinessReportConfig config) { proto.setContent(config.toString()); try { - m_configDao.updateBaseConfigByDomain(proto, BusinessConfigEntity.UPDATESET_FULL); + m_configDao.updateBaseConfigByDomain(proto); cacheConfigs(config, domain); + LOGGER.info("Updated business config, domain={}.", domain); return true; - } catch (DalException e) { + } catch (RuntimeException e) { + LOGGER.error("Unable to update business config, domain={}.", domain, e); Cat.logError(e); } @@ -249,6 +294,8 @@ public boolean updateConfigByDomain(BusinessReportConfig config) { } public boolean insertConfigByDomain(BusinessReportConfig config) { + ensureInitialized(); + BusinessConfig proto = m_configDao.createLocal(); String domain = config.getId(); @@ -260,8 +307,10 @@ public boolean insertConfigByDomain(BusinessReportConfig config) { try { m_configDao.insert(proto); cacheConfigs(config, domain); + LOGGER.info("Inserted business config, domain={}.", domain); return true; - } catch (DalException e) { + } catch (RuntimeException e) { + LOGGER.error("Unable to insert business config, domain={}.", domain, e); Cat.logError(e); } diff --git a/cat-core/src/main/java/com/dianping/cat/config/content/LocalResourceContentFetcher.java b/cat-core/src/main/java/com/dianping/cat/config/content/LocalResourceContentFetcher.java index 2f5350a4ff..0e5979a94d 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/content/LocalResourceContentFetcher.java +++ b/cat-core/src/main/java/com/dianping/cat/config/content/LocalResourceContentFetcher.java @@ -18,35 +18,29 @@ */ package com.dianping.cat.config.content; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Files; -import org.unidal.lookup.annotation.Named; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; -@Named(type = ContentFetcher.class) -public class LocalResourceContentFetcher implements ContentFetcher, LogEnabled { - private final String PATH = "/config/"; +public class LocalResourceContentFetcher implements ContentFetcher { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(LocalResourceContentFetcher.class); - private Logger m_logger; + private final String PATH = "/config/"; @Override public String getConfigContent(String configName) { String path = PATH + configName + ".xml"; String content = ""; - try { - content = Files.forIO().readFrom(this.getClass().getResourceAsStream(path), "utf-8"); + try (InputStream in = getClass().getResourceAsStream(path)) { + content = new String(in.readAllBytes(), StandardCharsets.UTF_8); } catch (Exception e) { - m_logger.warn("can't find local default config " + configName); + LOGGER.warn("can't find local default config {}", configName); Cat.logError(configName + " can't find", e); } return content; } - - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } } diff --git a/cat-core/src/main/java/com/dianping/cat/config/sample/SampleConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/sample/SampleConfigManager.java index 056232600d..5bf20c7298 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/sample/SampleConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/sample/SampleConfigManager.java @@ -18,53 +18,64 @@ */ package com.dianping.cat.config.sample; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.content.ContentFetcher; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.sample.entity.SampleConfig; import com.dianping.cat.sample.transform.DefaultSaxParser; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class SampleConfigManager implements Initializable { +public class SampleConfigManager { + private static final Logger LOGGER = LoggerFactory.getLogger(SampleConfigManager.class); private static final String CONFIG_NAME = "sampleConfig"; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private long m_modifyTime; private SampleConfig m_config; + private volatile boolean m_initialized; + public SampleConfig getConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + LOGGER.info("Loaded sample config from repository, configId={}, modifyTime={}.", m_configId, + m_modifyTime); + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Sample config is missing in repository, loading default content from fetcher.", e); + try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -74,14 +85,18 @@ public void initialize() throws InitializationException { m_configDao.insert(config); m_configId = config.getId(); m_config = DefaultSaxParser.parse(content); + LOGGER.info("Initialized sample config from default content, configId={}.", m_configId); } catch (Exception ex) { + LOGGER.error("Unable to initialize sample config from default content.", ex); Cat.logError(ex); } } catch (Exception e) { + LOGGER.error("Unable to load sample config from repository.", e); Cat.logError(e); } if (m_config == null) { m_config = new SampleConfig(); + LOGGER.warn("Sample config is empty after initialization, using a new empty config."); } TimerSyncTask.getInstance().register(new SyncHandler() { @@ -96,21 +111,34 @@ public String getName() { return CONFIG_NAME; } }); + m_initialized = true; + } + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); return storeConfig(); } catch (Exception e) { + LOGGER.error("Unable to parse sample config xml for insert. xmlLength={}.", xml == null ? 0 : xml.length(), + e); Cat.logError(e); return false; } } private void refreshConfig() throws Exception { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -119,6 +147,7 @@ private void refreshConfig() throws Exception { m_config = DefaultSaxParser.parse(content); m_modifyTime = modifyTime; + LOGGER.info("Refreshed sample config, configId={}, modifyTime={}.", m_configId, m_modifyTime); } } } @@ -132,8 +161,10 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); + LOGGER.info("Stored sample config, configId={}.", m_configId); } catch (Exception e) { + LOGGER.error("Unable to store sample config, configId={}.", m_configId, e); Cat.logError(e); return false; } diff --git a/cat-core/src/main/java/com/dianping/cat/config/server/ServerConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/server/ServerConfigManager.java index c410f1b9d5..2915d90f40 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/server/ServerConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/server/ServerConfigManager.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -30,19 +31,15 @@ import java.util.concurrent.ExecutorService; import java.util.regex.Pattern; -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.dal.jdbc.DalNotFoundException; -import org.unidal.helper.Files; -import org.unidal.helper.Splitters; -import org.unidal.helper.Threads; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; -import org.unidal.tuple.Pair; +import org.apache.commons.io.FileUtils; +import org.springframework.dao.EmptyResultDataAccessException; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads; import org.xml.sax.SAXException; +import com.google.common.base.Splitter; + import com.dianping.cat.Cat; import com.dianping.cat.Constants; import com.dianping.cat.config.content.ContentFetcher; @@ -57,13 +54,12 @@ import com.dianping.cat.configuration.server.entity.StorageConfig; import com.dianping.cat.configuration.server.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class ServerConfigManager implements LogEnabled, Initializable { +public class ServerConfigManager { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(ServerConfigManager.class); public static final String DUMP_DIR = "dump"; @@ -89,13 +85,11 @@ public class ServerConfigManager implements LogEnabled, Initializable { public ExecutorService m_threadPool; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; - private int m_configId; + private long m_configId; private long m_modifyTime; @@ -103,16 +97,23 @@ public class ServerConfigManager implements LogEnabled, Initializable { private volatile Server m_server; - private Logger m_logger; - private Set m_forcedStatisticTypePrefixes = new HashSet<>(); - @Override - public void enableLogging(Logger logger) { - m_logger = logger; + private volatile boolean m_initialized; + + private volatile boolean m_initializing; + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; } public ServerConfig getConfig() { + initialize(); + return m_config; } @@ -122,7 +123,7 @@ public String getConsoleDefaultDomain() { public List> getConsoleEndpoints() { String remoteServers = getProperty(REMOTE_SERVERS, ""); - List endpoints = Splitters.by(',').noEmptyItem().trim().split(remoteServers); + List endpoints = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(remoteServers); List> pairs = new ArrayList>(endpoints.size()); for (String endpoint : endpoints) { @@ -130,7 +131,7 @@ public List> getConsoleEndpoints() { String host = (pos > 0 ? endpoint.substring(0, pos) : endpoint); int port = (pos > 0 ? Integer.parseInt(endpoint.substring(pos + 1)) : 2281); - pairs.add(new Pair(host, port)); + pairs.add(Pair.of(host, port)); } return pairs; @@ -337,6 +338,10 @@ public int getModelServiceThreads() { } public String getProperty(String name, String defaultValue) { + if (!m_initialized && !m_initializing) { + initialize(); + } + if (m_server != null) { Property property = m_server.findProperty(name); @@ -360,6 +365,8 @@ public int getTpValueExpireMinute() { } public ServerConfig getServerConfig() { + initialize(); + return m_config; } @@ -387,87 +394,113 @@ public int getThreadsOfRealtimeAnalyzer(String name) { return Integer.parseInt(getProperty(name + "-analyzer-threads", "2")); } - @Override - public void initialize() throws InitializationException { - try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); - String content = config.getContent(); + public synchronized void initialize() { + if (m_initialized) { + return; + } + m_initializing = true; - m_configId = config.getId(); - m_modifyTime = config.getModifyDate().getTime(); - m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + try { try { - String content = m_fetcher.getConfigContent(CONFIG_NAME); - Config config = m_configDao.createLocal(); + Config config = m_configDao.findByName(CONFIG_NAME); + String content = config.getContent(); - config.setName(CONFIG_NAME); - config.setContent(content); - m_configDao.insert(config); m_configId = config.getId(); + m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (Exception ex) { - m_logger.error(e.getMessage()); - Cat.logError(ex); + SLF4J_LOGGER.info("Loaded server config from repository, configId={}, modifyTime={}.", m_configId, + m_modifyTime); + } catch (EmptyResultDataAccessException e) { + SLF4J_LOGGER.warn("Server config is missing in repository, loading default content from fetcher.", e); + + try { + String content = m_fetcher.getConfigContent(CONFIG_NAME); + Config config = m_configDao.createLocal(); + + config.setName(CONFIG_NAME); + config.setContent(content); + m_configDao.insert(config); + m_configId = config.getId(); + m_config = DefaultSaxParser.parse(content); + SLF4J_LOGGER.info("Initialized server config from default content, configId={}.", m_configId); + } catch (Exception ex) { + SLF4J_LOGGER.error("Unable to initialize server config from default content.", ex); + Cat.logError(ex); + } + } catch (Exception e) { + SLF4J_LOGGER.error("Unable to load server config from repository.", e); + Cat.logError(e); } - } catch (Exception e) { - m_logger.error(e.getMessage()); - Cat.logError(e); - } - if (m_config == null) { - try { - File localServerFile = new File(Cat.getCatHome(), "server.xml"); + if (m_config == null) { + try { + File localServerFile = new File(Cat.getCatHome(), "server.xml"); - m_logger.info("init cat server with cat server xml " + localServerFile); - initialize(localServerFile); - } catch (Exception e) { - m_logger.error(e.getMessage()); - Cat.logError(e); + SLF4J_LOGGER.info("init cat server with cat server xml {}", localServerFile); + initialize(localServerFile); + } catch (Exception e) { + SLF4J_LOGGER.error("Unable to initialize server config from local server.xml.", e); + Cat.logError(e); + } } - } - if (m_config == null) { - m_config = new ServerConfig(); - } + if (m_config == null) { + m_config = new ServerConfig(); + SLF4J_LOGGER.warn("Server config is empty after initialization, using a new empty config."); + } - m_config.accept(new ServerConfigValidator()); + m_config.accept(new ServerConfigValidator()); - try { - refreshServer(); - } catch (Exception e) { - m_logger.error(e.getMessage()); - Cat.logError(e); - } + try { + refreshServer(); + } catch (Exception e) { + SLF4J_LOGGER.error("Unable to refresh local server config view.", e); + Cat.logError(e); + } - prepare(); + prepare(); - TimerSyncTask.getInstance().register(new SyncHandler() { + TimerSyncTask.getInstance().register(new SyncHandler() { - @Override - public String getName() { - return CONFIG_NAME; - } + @Override + public String getName() { + return CONFIG_NAME; + } - @Override - public void handle() throws Exception { - refreshConfig(); - } - }); + @Override + public void handle() throws Exception { + refreshConfig(); + } + }); + m_initialized = true; + } finally { + m_initializing = false; + } } public void initialize(File configFile) throws Exception { - if (configFile != null && configFile.canRead()) { - m_logger.info(String.format("Loading configuration file(%s) ...", configFile.getCanonicalPath())); + m_initializing = true; - String xml = Files.forIO().readFrom(configFile, "utf-8"); - m_config = DefaultSaxParser.parse(xml); - } else { - if (configFile != null) { - m_logger.warn(String.format("Configuration file(%s) not found, IGNORED.", configFile.getCanonicalPath())); - } + try { + if (configFile != null && configFile.canRead()) { + SLF4J_LOGGER.info("Loading configuration file({}) ...", configFile.getCanonicalPath()); + + String xml = FileUtils.readFileToString(configFile, StandardCharsets.UTF_8); + m_config = DefaultSaxParser.parse(xml); + SLF4J_LOGGER.info("Loaded server config from local file, path={}.", configFile.getCanonicalPath()); + } else { + if (configFile != null) { + SLF4J_LOGGER.warn("Server config local file is not readable, path={}.", configFile.getCanonicalPath()); + } - m_config = new ServerConfig(); + m_config = new ServerConfig(); + } + m_config.accept(new ServerConfigValidator()); + refreshServer(); + prepare(); + m_initialized = true; + } finally { + m_initializing = false; } } @@ -477,6 +510,8 @@ public boolean insert(String xml) { return storeConfig(); } catch (Exception e) { + SLF4J_LOGGER.error("Unable to parse server config xml for insert. xmlLength={}.", + xml == null ? 0 : xml.length(), e); Cat.logError(e); return false; } @@ -532,14 +567,14 @@ public boolean isSendMachine() { private void prepare() { if (isLocalMode()) { - m_logger.warn("CAT server is running in LOCAL mode! No HDFS or MySQL will be accessed!"); + SLF4J_LOGGER.warn("CAT server is running in LOCAL mode! No HDFS or MySQL will be accessed!"); } - m_logger.info("CAT server is running with hdfs," + isHdfsOn()); - m_logger.info("CAT server is running with alert," + isAlertMachine()); - m_logger.info("CAT server is running with job," + isJobMachine()); + SLF4J_LOGGER.info("CAT server is running with hdfs,{}", isHdfsOn()); + SLF4J_LOGGER.info("CAT server is running with alert,{}", isAlertMachine()); + SLF4J_LOGGER.info("CAT server is running with job,{}", isJobMachine()); if (m_server != null) { - m_logger.info(m_server.toString()); + SLF4J_LOGGER.info("{}", m_server); if (isLocalMode()) { m_threadPool = Threads.forPool().getFixedThreadPool("Cat-ModelService", 5); @@ -550,7 +585,7 @@ private void prepare() { } private void refreshConfig() throws Exception { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -562,6 +597,7 @@ private void refreshConfig() throws Exception { m_modifyTime = modifyTime; refreshServer(); + SLF4J_LOGGER.info("Refreshed server config, configId={}, modifyTime={}.", m_configId, m_modifyTime); } } } @@ -580,8 +616,11 @@ private void refreshServer() throws SAXException, IOException { m_server = defaultServer; String forcedStatisticTypePrefixStr = getProperty("forced-statistic-type-prefixes", "Cellar.,Squirrel."); - List forcedStatisticTypePrefixes = Splitters.by(",").noEmptyItem().split(forcedStatisticTypePrefixStr); + List forcedStatisticTypePrefixes = Splitter.on(',').omitEmptyStrings() + .splitToList(forcedStatisticTypePrefixStr); m_forcedStatisticTypePrefixes = new HashSet<>(forcedStatisticTypePrefixes); + SLF4J_LOGGER.info("Refreshed server runtime config, localIp={}, forcedStatisticTypePrefixes={}.", ip, + m_forcedStatisticTypePrefixes); } public boolean storeConfig() { @@ -592,9 +631,11 @@ public boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); refreshServer(); + SLF4J_LOGGER.info("Stored server config, configId={}.", m_configId); } catch (Exception e) { + SLF4J_LOGGER.error("Unable to store server config, configId={}.", m_configId, e); Cat.logError(e); return false; } diff --git a/cat-core/src/main/java/com/dianping/cat/config/server/ServerFilterConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/server/ServerFilterConfigManager.java index 89b89886cf..3849ce73b7 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/server/ServerFilterConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/server/ServerFilterConfigManager.java @@ -22,13 +22,8 @@ import java.util.HashSet; import java.util.Set; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; import org.xml.sax.SAXException; +import org.springframework.dao.EmptyResultDataAccessException; import com.dianping.cat.Cat; import com.dianping.cat.config.content.ContentFetcher; @@ -36,29 +31,29 @@ import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; import com.dianping.cat.configuration.server.filter.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named(type = ServerFilterConfigManager.class) -public class ServerFilterConfigManager implements Initializable { +public class ServerFilterConfigManager { private static final String CONFIG_NAME = "serverFilter"; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; private volatile ServerFilterConfig m_config; - private int m_configId; + private long m_configId; private long m_modifyTime; + private volatile boolean m_initialized; + public boolean discardTransaction(String type, String name) { + ensureInitialized(); + if ("Cache.web".equals(type) || "ABTest".equals(type)) { return true; } @@ -69,6 +64,8 @@ public boolean discardTransaction(String type, String name) { } public String getAtomicMatchTypes() { + ensureInitialized(); + AtomicTreeConfig atomicTreeConfig = m_config.getAtomicTreeConfig(); if (atomicTreeConfig != null) { @@ -79,6 +76,8 @@ public String getAtomicMatchTypes() { } public String getAtomicStartTypes() { + ensureInitialized(); + AtomicTreeConfig atomicTreeConfig = m_config.getAtomicTreeConfig(); if (atomicTreeConfig != null) { @@ -89,26 +88,38 @@ public String getAtomicStartTypes() { } public ServerFilterConfig getConfig() { + ensureInitialized(); return m_config; } public Set getUnusedDomains() { + ensureInitialized(); + Set unusedDomains = new HashSet(); unusedDomains.addAll(m_config.getDomains()); return unusedDomains; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -139,9 +150,20 @@ public String getName() { return CONFIG_NAME; } }); + m_initialized = true; + } + + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); @@ -152,8 +174,8 @@ public boolean insert(String xml) { } } - private void refreshConfig() throws DalException, SAXException, IOException { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + private void refreshConfig() throws SAXException, IOException { + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -168,6 +190,8 @@ private void refreshConfig() throws DalException, SAXException, IOException { } public boolean storeConfig() { + ensureInitialized(); + try { Config config = m_configDao.createLocal(); @@ -175,7 +199,7 @@ public boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); } catch (Exception e) { Cat.logError(e); return false; @@ -184,6 +208,8 @@ public boolean storeConfig() { } public boolean validateDomain(String domain) { + ensureInitialized(); + return !m_config.getDomains().contains(domain) && !m_config.getCrashLogDomains().containsKey(domain); } diff --git a/cat-core/src/main/java/com/dianping/cat/config/transaction/TpValueStatisticConfigManager.java b/cat-core/src/main/java/com/dianping/cat/config/transaction/TpValueStatisticConfigManager.java index e32cff1637..a99936132a 100644 --- a/cat-core/src/main/java/com/dianping/cat/config/transaction/TpValueStatisticConfigManager.java +++ b/cat-core/src/main/java/com/dianping/cat/config/transaction/TpValueStatisticConfigManager.java @@ -21,11 +21,7 @@ import java.util.HashSet; import java.util.Set; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.springframework.dao.EmptyResultDataAccessException; import com.dianping.cat.Cat; import com.dianping.cat.config.content.ContentFetcher; @@ -34,46 +30,53 @@ import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; import com.dianping.cat.configuration.tp.transform.DefaultSaxParser; import com.dianping.cat.core.config.Config; -import com.dianping.cat.core.config.ConfigDao; -import com.dianping.cat.core.config.ConfigEntity; +import com.dianping.cat.mybatis.ConfigRepository; import com.dianping.cat.task.TimerSyncTask; -@Named -public class TpValueStatisticConfigManager implements Initializable { +public class TpValueStatisticConfigManager { public static final String DEFAULT = "default"; private static final String CONFIG_NAME = "tp-value-statistic-config"; - @Inject - protected ConfigDao m_configDao; + protected ConfigRepository m_configDao; - @Inject protected ContentFetcher m_fetcher; - @Inject private ServerConfigManager m_serverConfigManager; - private int m_configId; + private long m_configId; private long m_modifyTime; private TpValueStatisticConfig m_config; + private volatile boolean m_initialized; + public TpValueStatisticConfig getConfig() { + ensureInitialized(); return m_config; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + try { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); String content = config.getContent(); m_configId = config.getId(); m_modifyTime = config.getModifyDate().getTime(); m_config = DefaultSaxParser.parse(content); - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { try { String content = m_fetcher.getConfigContent(CONFIG_NAME); Config config = m_configDao.createLocal(); @@ -106,9 +109,12 @@ public void handle() throws Exception { } }); + m_initialized = true; } public boolean insert(String xml) { + ensureInitialized(); + try { m_config = DefaultSaxParser.parse(xml); @@ -119,8 +125,20 @@ public boolean insert(String xml) { } } + public void setConfigDao(ConfigRepository configDao) { + m_configDao = configDao; + } + + public void setFetcher(ContentFetcher fetcher) { + m_fetcher = fetcher; + } + + public void setServerConfigManager(ServerConfigManager serverConfigManager) { + m_serverConfigManager = serverConfigManager; + } + private void refreshConfig() throws Exception { - Config config = m_configDao.findByName(CONFIG_NAME, ConfigEntity.READSET_FULL); + Config config = m_configDao.findByName(CONFIG_NAME); long modifyTime = config.getModifyDate().getTime(); synchronized (this) { @@ -135,11 +153,15 @@ private void refreshConfig() throws Exception { } private boolean defaultContainsType(String type) { + ensureInitialized(); + Domain d = m_config.findDomain("default"); return d.getTransactionTypes().contains(type); } private boolean domainContainsType(String type, String domain) { + ensureInitialized(); + Domain d = m_config.findDomain(domain); return d != null && d.getTransactionTypes().contains(type); } @@ -170,7 +192,7 @@ private boolean storeConfig() { config.setKeyId(m_configId); config.setName(CONFIG_NAME); config.setContent(m_config.toString()); - m_configDao.updateByPK(config, ConfigEntity.UPDATESET_FULL); + m_configDao.updateByPK(config); } catch (Exception e) { Cat.logError(e); return false; @@ -180,6 +202,8 @@ private boolean storeConfig() { } public Set findTransactionTypesByDomain(String domain) { + ensureInitialized(); + Domain d = m_config.findDomain(domain); if (d != null) { diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/BaseEntity.java new file mode 100644 index 0000000000..082af339e3 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.business; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.business.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/Constants.java new file mode 100644 index 0000000000..997bab34bc --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/Constants.java @@ -0,0 +1,32 @@ +package com.dianping.cat.configuration.business; + +public class Constants { + + public static final String ATTR_ALARM = "alarm"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_PRIVILEGE = "privilege"; + + public static final String ATTR_SHOW_AVG = "show-avg"; + + public static final String ATTR_SHOW_COUNT = "show-count"; + + public static final String ATTR_SHOW_SUM = "show-sum"; + + public static final String ATTR_TITLE = "title"; + + public static final String ATTR_VIEW_ORDER = "view-order"; + + public static final String ELEMENT_PATTERN = "pattern"; + + public static final String ENTITY_BUSINESS_ITEM_CONFIG = "business-item-config"; + + public static final String ENTITY_BUSINESS_ITEM_CONFIGS = "business-item-configs"; + + public static final String ENTITY_BUSINESS_REPORT_CONFIG = "business-report-config"; + + public static final String ENTITY_CUSTOM_CONFIG = "custom-config"; + + public static final String ENTITY_CUSTOM_CONFIGS = "custom-configs"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/IEntity.java new file mode 100644 index 0000000000..b28f63cfcc --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.business; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/IVisitor.java new file mode 100644 index 0000000000..28db872d68 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.business; + +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public interface IVisitor { + + public void visitBusinessItemConfig(BusinessItemConfig businessItemConfig); + + public void visitBusinessReportConfig(BusinessReportConfig businessReportConfig); + + public void visitCustomConfig(CustomConfig customConfig); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessItemConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessItemConfig.java new file mode 100644 index 0000000000..948e8c40a6 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessItemConfig.java @@ -0,0 +1,175 @@ +package com.dianping.cat.configuration.business.entity; + +import static com.dianping.cat.configuration.business.Constants.ATTR_ID; +import static com.dianping.cat.configuration.business.Constants.ENTITY_BUSINESS_ITEM_CONFIG; + +import com.dianping.cat.configuration.business.BaseEntity; +import com.dianping.cat.configuration.business.IVisitor; + +public class BusinessItemConfig extends BaseEntity { + private String m_id; + + private double m_viewOrder; + + private String m_title; + + private boolean m_showCount; + + private boolean m_showAvg; + + private boolean m_showSum; + + private boolean m_alarm = false; + + private boolean m_privilege = false; + + public BusinessItemConfig() { + } + + public BusinessItemConfig(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitBusinessItemConfig(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BusinessItemConfig) { + BusinessItemConfig _o = (BusinessItemConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public boolean getAlarm() { + return m_alarm; + } + + public String getId() { + return m_id; + } + + public boolean getPrivilege() { + return m_privilege; + } + + public boolean getShowAvg() { + return m_showAvg; + } + + public boolean getShowCount() { + return m_showCount; + } + + public boolean getShowSum() { + return m_showSum; + } + + public String getTitle() { + return m_title; + } + + public double getViewOrder() { + return m_viewOrder; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public boolean isAlarm() { + return m_alarm; + } + + public boolean isPrivilege() { + return m_privilege; + } + + public boolean isShowAvg() { + return m_showAvg; + } + + public boolean isShowCount() { + return m_showCount; + } + + public boolean isShowSum() { + return m_showSum; + } + + @Override + public void mergeAttributes(BusinessItemConfig other) { + assertAttributeEquals(other, ENTITY_BUSINESS_ITEM_CONFIG, ATTR_ID, m_id, other.getId()); + + m_viewOrder = other.getViewOrder(); + + if (other.getTitle() != null) { + m_title = other.getTitle(); + } + + m_showCount = other.getShowCount(); + + m_showAvg = other.getShowAvg(); + + m_showSum = other.getShowSum(); + + m_alarm = other.getAlarm(); + + m_privilege = other.getPrivilege(); + } + + public BusinessItemConfig setAlarm(boolean alarm) { + m_alarm = alarm; + return this; + } + + public BusinessItemConfig setId(String id) { + m_id = id; + return this; + } + + public BusinessItemConfig setPrivilege(boolean privilege) { + m_privilege = privilege; + return this; + } + + public BusinessItemConfig setShowAvg(boolean showAvg) { + m_showAvg = showAvg; + return this; + } + + public BusinessItemConfig setShowCount(boolean showCount) { + m_showCount = showCount; + return this; + } + + public BusinessItemConfig setShowSum(boolean showSum) { + m_showSum = showSum; + return this; + } + + public BusinessItemConfig setTitle(String title) { + m_title = title; + return this; + } + + public BusinessItemConfig setViewOrder(double viewOrder) { + m_viewOrder = viewOrder; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessReportConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessReportConfig.java new file mode 100644 index 0000000000..b82ebdbd97 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/BusinessReportConfig.java @@ -0,0 +1,109 @@ +package com.dianping.cat.configuration.business.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.business.BaseEntity; +import com.dianping.cat.configuration.business.IVisitor; + +public class BusinessReportConfig extends BaseEntity { + private String m_id; + + private Map m_businessItemConfigs = new LinkedHashMap(); + + private Map m_customConfigs = new LinkedHashMap(); + + public BusinessReportConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitBusinessReportConfig(this); + } + + public BusinessReportConfig addBusinessItemConfig(BusinessItemConfig businessItemConfig) { + m_businessItemConfigs.put(businessItemConfig.getId(), businessItemConfig); + return this; + } + + public BusinessReportConfig addCustomConfig(CustomConfig customConfig) { + m_customConfigs.put(customConfig.getId(), customConfig); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof BusinessReportConfig) { + BusinessReportConfig _o = (BusinessReportConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + if (!equals(getBusinessItemConfigs(), _o.getBusinessItemConfigs())) { + return false; + } + + if (!equals(getCustomConfigs(), _o.getCustomConfigs())) { + return false; + } + + + return true; + } + + return false; + } + + public BusinessItemConfig findBusinessItemConfig(String id) { + return m_businessItemConfigs.get(id); + } + + public CustomConfig findCustomConfig(String id) { + return m_customConfigs.get(id); + } + + public Map getBusinessItemConfigs() { + return m_businessItemConfigs; + } + + public Map getCustomConfigs() { + return m_customConfigs; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + hash = hash * 31 + (m_businessItemConfigs == null ? 0 : m_businessItemConfigs.hashCode()); + hash = hash * 31 + (m_customConfigs == null ? 0 : m_customConfigs.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(BusinessReportConfig other) { + if (other.getId() != null) { + m_id = other.getId(); + } + } + + public BusinessItemConfig removeBusinessItemConfig(String id) { + return m_businessItemConfigs.remove(id); + } + + public CustomConfig removeCustomConfig(String id) { + return m_customConfigs.remove(id); + } + + public BusinessReportConfig setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/CustomConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/CustomConfig.java new file mode 100644 index 0000000000..68f12503bb --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/entity/CustomConfig.java @@ -0,0 +1,135 @@ +package com.dianping.cat.configuration.business.entity; + +import static com.dianping.cat.configuration.business.Constants.ATTR_ID; +import static com.dianping.cat.configuration.business.Constants.ENTITY_CUSTOM_CONFIG; + +import com.dianping.cat.configuration.business.BaseEntity; +import com.dianping.cat.configuration.business.IVisitor; + +public class CustomConfig extends BaseEntity { + private String m_id; + + private double m_viewOrder; + + private String m_title; + + private boolean m_alarm = false; + + private boolean m_privilege = false; + + private String m_pattern; + + public CustomConfig() { + } + + public CustomConfig(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCustomConfig(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CustomConfig) { + CustomConfig _o = (CustomConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public boolean getAlarm() { + return m_alarm; + } + + public String getId() { + return m_id; + } + + public String getPattern() { + return m_pattern; + } + + public boolean getPrivilege() { + return m_privilege; + } + + public String getTitle() { + return m_title; + } + + public double getViewOrder() { + return m_viewOrder; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + public boolean isAlarm() { + return m_alarm; + } + + public boolean isPrivilege() { + return m_privilege; + } + + @Override + public void mergeAttributes(CustomConfig other) { + assertAttributeEquals(other, ENTITY_CUSTOM_CONFIG, ATTR_ID, m_id, other.getId()); + + m_viewOrder = other.getViewOrder(); + + if (other.getTitle() != null) { + m_title = other.getTitle(); + } + + m_alarm = other.getAlarm(); + + m_privilege = other.getPrivilege(); + } + + public CustomConfig setAlarm(boolean alarm) { + m_alarm = alarm; + return this; + } + + public CustomConfig setId(String id) { + m_id = id; + return this; + } + + public CustomConfig setPattern(String pattern) { + m_pattern = pattern; + return this; + } + + public CustomConfig setPrivilege(boolean privilege) { + m_privilege = privilege; + return this; + } + + public CustomConfig setTitle(String title) { + m_title = title; + return this; + } + + public CustomConfig setViewOrder(double viewOrder) { + m_viewOrder = viewOrder; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultLinker.java new file mode 100644 index 0000000000..9ee79c7ad1 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultLinker.java @@ -0,0 +1,55 @@ +package com.dianping.cat.configuration.business.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onBusinessItemConfig(final BusinessReportConfig parent, final BusinessItemConfig businessItemConfig) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addBusinessItemConfig(businessItemConfig); + } + }); + } else { + parent.addBusinessItemConfig(businessItemConfig); + } + + return true; + } + + @Override + public boolean onCustomConfig(final BusinessReportConfig parent, final CustomConfig customConfig) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addCustomConfig(customConfig); + } + }); + } else { + parent.addCustomConfig(customConfig); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..e3fa30f3a3 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxMaker.java @@ -0,0 +1,129 @@ +package com.dianping.cat.configuration.business.transform; + +import static com.dianping.cat.configuration.business.Constants.ATTR_ALARM; +import static com.dianping.cat.configuration.business.Constants.ATTR_ID; +import static com.dianping.cat.configuration.business.Constants.ATTR_PRIVILEGE; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_AVG; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_COUNT; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_SUM; +import static com.dianping.cat.configuration.business.Constants.ATTR_TITLE; +import static com.dianping.cat.configuration.business.Constants.ATTR_VIEW_ORDER; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public BusinessItemConfig buildBusinessItemConfig(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String viewOrder = attributes.getValue(ATTR_VIEW_ORDER); + String title = attributes.getValue(ATTR_TITLE); + String showCount = attributes.getValue(ATTR_SHOW_COUNT); + String showAvg = attributes.getValue(ATTR_SHOW_AVG); + String showSum = attributes.getValue(ATTR_SHOW_SUM); + String alarm = attributes.getValue(ATTR_ALARM); + String privilege = attributes.getValue(ATTR_PRIVILEGE); + BusinessItemConfig businessItemConfig = new BusinessItemConfig(id); + + if (viewOrder != null) { + businessItemConfig.setViewOrder(convert(Double.class, viewOrder, 0.0)); + } + + if (title != null) { + businessItemConfig.setTitle(title); + } + + if (showCount != null) { + businessItemConfig.setShowCount(convert(Boolean.class, showCount, false)); + } + + if (showAvg != null) { + businessItemConfig.setShowAvg(convert(Boolean.class, showAvg, false)); + } + + if (showSum != null) { + businessItemConfig.setShowSum(convert(Boolean.class, showSum, false)); + } + + if (alarm != null) { + businessItemConfig.setAlarm(convert(Boolean.class, alarm, false)); + } + + if (privilege != null) { + businessItemConfig.setPrivilege(convert(Boolean.class, privilege, false)); + } + + return businessItemConfig; + } + + @Override + public BusinessReportConfig buildBusinessReportConfig(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + BusinessReportConfig businessReportConfig = new BusinessReportConfig(); + + if (id != null) { + businessReportConfig.setId(id); + } + + return businessReportConfig; + } + + @Override + public CustomConfig buildCustomConfig(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String viewOrder = attributes.getValue(ATTR_VIEW_ORDER); + String title = attributes.getValue(ATTR_TITLE); + String alarm = attributes.getValue(ATTR_ALARM); + String privilege = attributes.getValue(ATTR_PRIVILEGE); + CustomConfig customConfig = new CustomConfig(id); + + if (viewOrder != null) { + customConfig.setViewOrder(convert(Double.class, viewOrder, 0.0)); + } + + if (title != null) { + customConfig.setTitle(title); + } + + if (alarm != null) { + customConfig.setAlarm(convert(Boolean.class, alarm, false)); + } + + if (privilege != null) { + customConfig.setPrivilege(convert(Boolean.class, privilege, false)); + } + + return customConfig; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..d1fdafb8ab --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultSaxParser.java @@ -0,0 +1,261 @@ +package com.dianping.cat.configuration.business.transform; + +import static com.dianping.cat.configuration.business.Constants.ELEMENT_PATTERN; + +import static com.dianping.cat.configuration.business.Constants.ENTITY_BUSINESS_ITEM_CONFIG; +import static com.dianping.cat.configuration.business.Constants.ENTITY_BUSINESS_REPORT_CONFIG; +import static com.dianping.cat.configuration.business.Constants.ENTITY_CUSTOM_CONFIG; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.business.IEntity; +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static BusinessReportConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(BusinessReportConfig.class, new InputSource(removeBOM(in))); + } + + public static BusinessReportConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(BusinessReportConfig.class, new InputSource(removeBOM(reader))); + } + + public static BusinessReportConfig parse(String xml) throws SAXException, IOException { + return parseEntity(BusinessReportConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof CustomConfig) { + CustomConfig customConfig = (CustomConfig) currentObj; + + if (ELEMENT_PATTERN.equals(currentTag)) { + customConfig.setPattern(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForBusinessItemConfig(BusinessItemConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForBusinessReportConfig(BusinessReportConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_BUSINESS_ITEM_CONFIG.equals(qName)) { + BusinessItemConfig businessItemConfig = m_maker.buildBusinessItemConfig(attributes); + + m_linker.onBusinessItemConfig(parentObj, businessItemConfig); + m_objs.push(businessItemConfig); + } else if (ENTITY_CUSTOM_CONFIG.equals(qName)) { + CustomConfig customConfig = m_maker.buildCustomConfig(attributes); + + m_linker.onCustomConfig(parentObj, customConfig); + m_objs.push(customConfig); + } else { + throw new SAXException(String.format("Element(%s) is not expected under business-report-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForCustomConfig(CustomConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_PATTERN.equals(qName)) { + m_objs.push(parentObj); + } else { + throw new SAXException(String.format("Element(%s) is not expected under custom-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_BUSINESS_REPORT_CONFIG.equals(qName)) { + BusinessReportConfig businessReportConfig = m_maker.buildBusinessReportConfig(attributes); + + m_entity = businessReportConfig; + m_objs.push(businessReportConfig); + m_tags.push(qName); + } else if (ENTITY_BUSINESS_ITEM_CONFIG.equals(qName)) { + BusinessItemConfig businessItemConfig = m_maker.buildBusinessItemConfig(attributes); + + m_entity = businessItemConfig; + m_objs.push(businessItemConfig); + m_tags.push(qName); + } else if (ENTITY_CUSTOM_CONFIG.equals(qName)) { + CustomConfig customConfig = m_maker.buildCustomConfig(attributes); + + m_entity = customConfig; + m_objs.push(customConfig); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof BusinessReportConfig) { + parseForBusinessReportConfig((BusinessReportConfig) parent, tag, qName, attributes); + } else if (parent instanceof BusinessItemConfig) { + parseForBusinessItemConfig((BusinessItemConfig) parent, tag, qName, attributes); + } else if (parent instanceof CustomConfig) { + parseForCustomConfig((CustomConfig) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..78d6b00272 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/DefaultXmlBuilder.java @@ -0,0 +1,280 @@ +package com.dianping.cat.configuration.business.transform; + +import static com.dianping.cat.configuration.business.Constants.ATTR_ALARM; +import static com.dianping.cat.configuration.business.Constants.ATTR_ID; +import static com.dianping.cat.configuration.business.Constants.ATTR_PRIVILEGE; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_AVG; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_COUNT; +import static com.dianping.cat.configuration.business.Constants.ATTR_SHOW_SUM; +import static com.dianping.cat.configuration.business.Constants.ATTR_TITLE; +import static com.dianping.cat.configuration.business.Constants.ATTR_VIEW_ORDER; +import static com.dianping.cat.configuration.business.Constants.ELEMENT_PATTERN; +import static com.dianping.cat.configuration.business.Constants.ENTITY_BUSINESS_ITEM_CONFIG; +import static com.dianping.cat.configuration.business.Constants.ENTITY_BUSINESS_REPORT_CONFIG; +import static com.dianping.cat.configuration.business.Constants.ENTITY_CUSTOM_CONFIG; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.business.IEntity; +import com.dianping.cat.configuration.business.IVisitor; +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + @Override + public void visitBusinessItemConfig(BusinessItemConfig businessItemConfig) { + startTag(ENTITY_BUSINESS_ITEM_CONFIG, true, null, ATTR_ID, businessItemConfig.getId(), ATTR_VIEW_ORDER, businessItemConfig.getViewOrder(), ATTR_TITLE, businessItemConfig.getTitle(), ATTR_SHOW_COUNT, businessItemConfig.isShowCount(), ATTR_SHOW_AVG, businessItemConfig.isShowAvg(), ATTR_SHOW_SUM, businessItemConfig.isShowSum(), ATTR_ALARM, businessItemConfig.isAlarm(), ATTR_PRIVILEGE, businessItemConfig.isPrivilege()); + } + + @Override + public void visitBusinessReportConfig(BusinessReportConfig businessReportConfig) { + startTag(ENTITY_BUSINESS_REPORT_CONFIG, null, ATTR_ID, businessReportConfig.getId()); + + if (!businessReportConfig.getBusinessItemConfigs().isEmpty()) { + for (BusinessItemConfig businessItemConfig : businessReportConfig.getBusinessItemConfigs().values()) { + businessItemConfig.accept(m_visitor); + } + } + + if (!businessReportConfig.getCustomConfigs().isEmpty()) { + for (CustomConfig customConfig : businessReportConfig.getCustomConfigs().values()) { + customConfig.accept(m_visitor); + } + } + + endTag(ENTITY_BUSINESS_REPORT_CONFIG); + } + + @Override + public void visitCustomConfig(CustomConfig customConfig) { + startTag(ENTITY_CUSTOM_CONFIG, null, ATTR_ID, customConfig.getId(), ATTR_VIEW_ORDER, customConfig.getViewOrder(), ATTR_TITLE, customConfig.getTitle(), ATTR_ALARM, customConfig.isAlarm(), ATTR_PRIVILEGE, customConfig.isPrivilege()); + + element(ELEMENT_PATTERN, customConfig.getPattern(), null, true); + + endTag(ENTITY_CUSTOM_CONFIG); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/ILinker.java new file mode 100644 index 0000000000..5ac25ebabe --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.configuration.business.transform; + +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public interface ILinker { + + public boolean onBusinessItemConfig(BusinessReportConfig parent, BusinessItemConfig businessItemConfig); + + public boolean onCustomConfig(BusinessReportConfig parent, CustomConfig customConfig); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IMaker.java new file mode 100644 index 0000000000..cc052cf5c7 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.business.transform; + +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public interface IMaker { + + public BusinessItemConfig buildBusinessItemConfig(T node); + + public BusinessReportConfig buildBusinessReportConfig(T node); + + public CustomConfig buildCustomConfig(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IParser.java new file mode 100644 index 0000000000..3e09526de0 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/business/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.business.transform; + +import com.dianping.cat.configuration.business.entity.BusinessItemConfig; +import com.dianping.cat.configuration.business.entity.BusinessReportConfig; +import com.dianping.cat.configuration.business.entity.CustomConfig; + +public interface IParser { + public BusinessReportConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForBusinessItemConfig(IMaker maker, ILinker linker, BusinessItemConfig parent, T node); + + public void parseForCustomConfig(IMaker maker, ILinker linker, CustomConfig parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/BaseEntity.java new file mode 100644 index 0000000000..e8b87ca8fd --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.message; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.message.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/Constants.java new file mode 100644 index 0000000000..62a8b87d97 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/Constants.java @@ -0,0 +1,24 @@ +package com.dianping.cat.configuration.message; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_VALUE = "value"; + + public static final String ELEMENT_MATCH_TYPES = "match-types"; + + public static final String ELEMENT_START_TYPES = "start-types"; + + public static final String ENTITY_ATOMIC_MESSAGE_CONFIG = "atomic-message-config"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_PROPERTIES = "properties"; + + public static final String ENTITY_PROPERTY = "property"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/IEntity.java new file mode 100644 index 0000000000..6dbff194fa --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.message; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/IVisitor.java new file mode 100644 index 0000000000..e2e9dd6a35 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.message; + +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public interface IVisitor { + + public void visitAtomicMessageConfig(AtomicMessageConfig atomicMessageConfig); + + public void visitDomain(Domain domain); + + public void visitProperty(Property property); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/AtomicMessageConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/AtomicMessageConfig.java new file mode 100644 index 0000000000..08b2313c50 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/AtomicMessageConfig.java @@ -0,0 +1,66 @@ +package com.dianping.cat.configuration.message.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.message.BaseEntity; +import com.dianping.cat.configuration.message.IVisitor; + +public class AtomicMessageConfig extends BaseEntity { + private Map m_domains = new LinkedHashMap(); + + public AtomicMessageConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAtomicMessageConfig(this); + } + + public AtomicMessageConfig addDomain(Domain domain) { + m_domains.put(domain.getId(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AtomicMessageConfig) { + AtomicMessageConfig _o = (AtomicMessageConfig) obj; + + if (!equals(getDomains(), _o.getDomains())) { + return false; + } + + + return true; + } + + return false; + } + + public Domain findDomain(String id) { + return m_domains.get(id); + } + + public Map getDomains() { + return m_domains; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domains == null ? 0 : m_domains.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(AtomicMessageConfig other) { + } + + public Domain removeDomain(String id) { + return m_domains.remove(id); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Domain.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Domain.java new file mode 100644 index 0000000000..e700f89d02 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Domain.java @@ -0,0 +1,107 @@ +package com.dianping.cat.configuration.message.entity; + +import static com.dianping.cat.configuration.message.Constants.ATTR_ID; +import static com.dianping.cat.configuration.message.Constants.ENTITY_DOMAIN; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.message.BaseEntity; +import com.dianping.cat.configuration.message.IVisitor; + +public class Domain extends BaseEntity { + private String m_id; + + private String m_startTypes; + + private String m_matchTypes; + + private Map m_properties = new LinkedHashMap(); + + public Domain() { + } + + public Domain(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + public Domain addProperty(Property property) { + m_properties.put(property.getName(), property); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Property findProperty(String name) { + return m_properties.get(name); + } + + public String getId() { + return m_id; + } + + public String getMatchTypes() { + return m_matchTypes; + } + + public Map getProperties() { + return m_properties; + } + + public String getStartTypes() { + return m_startTypes; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_ID, m_id, other.getId()); + + } + + public Property removeProperty(String name) { + return m_properties.remove(name); + } + + public Domain setId(String id) { + m_id = id; + return this; + } + + public Domain setMatchTypes(String matchTypes) { + m_matchTypes = matchTypes; + return this; + } + + public Domain setStartTypes(String startTypes) { + m_startTypes = startTypes; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Property.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Property.java new file mode 100644 index 0000000000..1efb4bf653 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/entity/Property.java @@ -0,0 +1,77 @@ +package com.dianping.cat.configuration.message.entity; + +import static com.dianping.cat.configuration.message.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.message.Constants.ENTITY_PROPERTY; + +import com.dianping.cat.configuration.message.BaseEntity; +import com.dianping.cat.configuration.message.IVisitor; + +public class Property extends BaseEntity { + private String m_name; + + private String m_value; + + public Property() { + } + + public Property(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitProperty(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Property) { + Property _o = (Property) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public String getName() { + return m_name; + } + + public String getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Property other) { + assertAttributeEquals(other, ENTITY_PROPERTY, ATTR_NAME, m_name, other.getName()); + + if (other.getValue() != null) { + m_value = other.getValue(); + } + } + + public Property setName(String name) { + m_name = name; + return this; + } + + public Property setValue(String value) { + m_value = value; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultLinker.java new file mode 100644 index 0000000000..51fdcff310 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultLinker.java @@ -0,0 +1,55 @@ +package com.dianping.cat.configuration.message.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDomain(final AtomicMessageConfig parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } + + @Override + public boolean onProperty(final Domain parent, final Property property) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addProperty(property); + } + }); + } else { + parent.addProperty(property); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..d7ed487cd4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxMaker.java @@ -0,0 +1,69 @@ +package com.dianping.cat.configuration.message.transform; + +import static com.dianping.cat.configuration.message.Constants.ATTR_ID; +import static com.dianping.cat.configuration.message.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.message.Constants.ATTR_VALUE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AtomicMessageConfig buildAtomicMessageConfig(Attributes attributes) { + AtomicMessageConfig atomicMessageConfig = new AtomicMessageConfig(); + + return atomicMessageConfig; + } + + @Override + public Domain buildDomain(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Domain domain = new Domain(id); + + return domain; + } + + @Override + public Property buildProperty(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + String value = attributes.getValue(ATTR_VALUE); + Property property = new Property(name); + + if (value != null) { + property.setValue(value); + } + + return property; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..30332e7966 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultSaxParser.java @@ -0,0 +1,265 @@ +package com.dianping.cat.configuration.message.transform; + +import static com.dianping.cat.configuration.message.Constants.ELEMENT_MATCH_TYPES; +import static com.dianping.cat.configuration.message.Constants.ELEMENT_START_TYPES; + +import static com.dianping.cat.configuration.message.Constants.ENTITY_ATOMIC_MESSAGE_CONFIG; +import static com.dianping.cat.configuration.message.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.message.Constants.ENTITY_PROPERTY; +import static com.dianping.cat.configuration.message.Constants.ENTITY_PROPERTIES; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.message.IEntity; +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static AtomicMessageConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(AtomicMessageConfig.class, new InputSource(removeBOM(in))); + } + + public static AtomicMessageConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(AtomicMessageConfig.class, new InputSource(removeBOM(reader))); + } + + public static AtomicMessageConfig parse(String xml) throws SAXException, IOException { + return parseEntity(AtomicMessageConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof Domain) { + Domain domain = (Domain) currentObj; + + if (ELEMENT_START_TYPES.equals(currentTag)) { + domain.setStartTypes(getText()); + } else if (ELEMENT_MATCH_TYPES.equals(currentTag)) { + domain.setMatchTypes(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAtomicMessageConfig(AtomicMessageConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under atomic-message-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_START_TYPES.equals(qName) || ELEMENT_MATCH_TYPES.equals(qName) || ENTITY_PROPERTIES.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_PROPERTY.equals(qName)) { + Property property = m_maker.buildProperty(attributes); + + m_linker.onProperty(parentObj, property); + m_objs.push(property); + } else { + throw new SAXException(String.format("Element(%s) is not expected under domain!", qName)); + } + + m_tags.push(qName); + } + + private void parseForProperty(Property parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_ATOMIC_MESSAGE_CONFIG.equals(qName)) { + AtomicMessageConfig atomicMessageConfig = m_maker.buildAtomicMessageConfig(attributes); + + m_entity = atomicMessageConfig; + m_objs.push(atomicMessageConfig); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else if (ENTITY_PROPERTY.equals(qName)) { + Property property = m_maker.buildProperty(attributes); + + m_entity = property; + m_objs.push(property); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof AtomicMessageConfig) { + parseForAtomicMessageConfig((AtomicMessageConfig) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else if (parent instanceof Property) { + parseForProperty((Property) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..b69f8c5885 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/DefaultXmlBuilder.java @@ -0,0 +1,283 @@ +package com.dianping.cat.configuration.message.transform; + +import static com.dianping.cat.configuration.message.Constants.ATTR_ID; +import static com.dianping.cat.configuration.message.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.message.Constants.ATTR_VALUE; +import static com.dianping.cat.configuration.message.Constants.ELEMENT_MATCH_TYPES; +import static com.dianping.cat.configuration.message.Constants.ELEMENT_START_TYPES; +import static com.dianping.cat.configuration.message.Constants.ENTITY_ATOMIC_MESSAGE_CONFIG; +import static com.dianping.cat.configuration.message.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.message.Constants.ENTITY_PROPERTIES; +import static com.dianping.cat.configuration.message.Constants.ENTITY_PROPERTY; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.message.IEntity; +import com.dianping.cat.configuration.message.IVisitor; +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + @Override + public void visitAtomicMessageConfig(AtomicMessageConfig atomicMessageConfig) { + startTag(ENTITY_ATOMIC_MESSAGE_CONFIG, null); + + if (!atomicMessageConfig.getDomains().isEmpty()) { + for (Domain domain : atomicMessageConfig.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_ATOMIC_MESSAGE_CONFIG); + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, null, ATTR_ID, domain.getId()); + + element(ELEMENT_START_TYPES, domain.getStartTypes(), null, true); + + element(ELEMENT_MATCH_TYPES, domain.getMatchTypes(), null, true); + + if (!domain.getProperties().isEmpty()) { + startTag(ENTITY_PROPERTIES); + + for (Property property : domain.getProperties().values()) { + property.accept(m_visitor); + } + + endTag(ENTITY_PROPERTIES); + } + + endTag(ENTITY_DOMAIN); + } + + @Override + public void visitProperty(Property property) { + startTag(ENTITY_PROPERTY, true, null, ATTR_NAME, property.getName(), ATTR_VALUE, property.getValue()); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/ILinker.java new file mode 100644 index 0000000000..3218b9af7f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.configuration.message.transform; + +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public interface ILinker { + + public boolean onDomain(AtomicMessageConfig parent, Domain domain); + + public boolean onProperty(Domain parent, Property property); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IMaker.java new file mode 100644 index 0000000000..32e21d34f4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.message.transform; + +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public interface IMaker { + + public AtomicMessageConfig buildAtomicMessageConfig(T node); + + public Domain buildDomain(T node); + + public Property buildProperty(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IParser.java new file mode 100644 index 0000000000..4c3da33358 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/message/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.message.transform; + +import com.dianping.cat.configuration.message.entity.AtomicMessageConfig; +import com.dianping.cat.configuration.message.entity.Domain; +import com.dianping.cat.configuration.message.entity.Property; + +public interface IParser { + public AtomicMessageConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); + + public void parseForProperty(IMaker maker, ILinker linker, Property parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/BaseEntity.java new file mode 100644 index 0000000000..9164fe9fd9 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.reload; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.reload.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/Constants.java new file mode 100644 index 0000000000..b483e6965a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/Constants.java @@ -0,0 +1,16 @@ +package com.dianping.cat.configuration.reload; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ENTITY_REPORT_PERIOD = "report-period"; + + public static final String ENTITY_REPORT_PERIODS = "report-periods"; + + public static final String ENTITY_REPORT_RELOAD_CONFIG = "report-reload-config"; + + public static final String ENTITY_REPORT_TYPE = "report-type"; + + public static final String ENTITY_REPORT_TYPES = "report-types"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/IEntity.java new file mode 100644 index 0000000000..eebf591cef --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.reload; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/IVisitor.java new file mode 100644 index 0000000000..05d0922ae5 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.reload; + +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public interface IVisitor { + + public void visitReportPeriod(ReportPeriod reportPeriod); + + public void visitReportReloadConfig(ReportReloadConfig reportReloadConfig); + + public void visitReportType(ReportType reportType); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportPeriod.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportPeriod.java new file mode 100644 index 0000000000..27b2509526 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportPeriod.java @@ -0,0 +1,58 @@ +package com.dianping.cat.configuration.reload.entity; + +import com.dianping.cat.configuration.reload.BaseEntity; +import com.dianping.cat.configuration.reload.IVisitor; + +public class ReportPeriod extends BaseEntity { + private String m_id; + + public ReportPeriod() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitReportPeriod(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ReportPeriod) { + ReportPeriod _o = (ReportPeriod) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ReportPeriod other) { + if (other.getId() != null) { + m_id = other.getId(); + } + } + + public ReportPeriod setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportReloadConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportReloadConfig.java new file mode 100644 index 0000000000..1566a6e7e4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportReloadConfig.java @@ -0,0 +1,66 @@ +package com.dianping.cat.configuration.reload.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.reload.BaseEntity; +import com.dianping.cat.configuration.reload.IVisitor; + +public class ReportReloadConfig extends BaseEntity { + private Map m_reportTypes = new LinkedHashMap(); + + public ReportReloadConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitReportReloadConfig(this); + } + + public ReportReloadConfig addReportType(ReportType reportType) { + m_reportTypes.put(reportType.getId(), reportType); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ReportReloadConfig) { + ReportReloadConfig _o = (ReportReloadConfig) obj; + + if (!equals(getReportTypes(), _o.getReportTypes())) { + return false; + } + + + return true; + } + + return false; + } + + public ReportType findReportType(String id) { + return m_reportTypes.get(id); + } + + public Map getReportTypes() { + return m_reportTypes; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_reportTypes == null ? 0 : m_reportTypes.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ReportReloadConfig other) { + } + + public ReportType removeReportType(String id) { + return m_reportTypes.remove(id); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportType.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportType.java new file mode 100644 index 0000000000..252392f220 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/entity/ReportType.java @@ -0,0 +1,77 @@ +package com.dianping.cat.configuration.reload.entity; + +import static com.dianping.cat.configuration.reload.Constants.ATTR_ID; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_TYPE; + +import java.util.ArrayList; +import java.util.List; + +import com.dianping.cat.configuration.reload.BaseEntity; +import com.dianping.cat.configuration.reload.IVisitor; + +public class ReportType extends BaseEntity { + private String m_id; + + private List m_reportPeriods = new ArrayList(); + + public ReportType() { + } + + public ReportType(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitReportType(this); + } + + public ReportType addReportPeriod(ReportPeriod reportPeriod) { + m_reportPeriods.add(reportPeriod); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ReportType) { + ReportType _o = (ReportType) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public List getReportPeriods() { + return m_reportPeriods; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ReportType other) { + assertAttributeEquals(other, ENTITY_REPORT_TYPE, ATTR_ID, m_id, other.getId()); + + } + + public ReportType setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultLinker.java new file mode 100644 index 0000000000..a1d6d7eea4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultLinker.java @@ -0,0 +1,45 @@ +package com.dianping.cat.configuration.reload.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onReportPeriod(final ReportType parent, final ReportPeriod reportPeriod) { + parent.addReportPeriod(reportPeriod); + return true; + } + + @Override + public boolean onReportType(final ReportReloadConfig parent, final ReportType reportType) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addReportType(reportType); + } + }); + } else { + parent.addReportType(reportType); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..22e3a6ba83 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxMaker.java @@ -0,0 +1,66 @@ +package com.dianping.cat.configuration.reload.transform; + +import static com.dianping.cat.configuration.reload.Constants.ATTR_ID; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public class DefaultSaxMaker implements IMaker { + + @Override + public ReportPeriod buildReportPeriod(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + ReportPeriod reportPeriod = new ReportPeriod(); + + if (id != null) { + reportPeriod.setId(id); + } + + return reportPeriod; + } + + @Override + public ReportReloadConfig buildReportReloadConfig(Attributes attributes) { + ReportReloadConfig reportReloadConfig = new ReportReloadConfig(); + + return reportReloadConfig; + } + + @Override + public ReportType buildReportType(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + ReportType reportType = new ReportType(id); + + return reportType; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..2bfc91194d --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultSaxParser.java @@ -0,0 +1,250 @@ +package com.dianping.cat.configuration.reload.transform; + +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_PERIOD; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_RELOAD_CONFIG; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_TYPE; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.reload.IEntity; +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static ReportReloadConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(ReportReloadConfig.class, new InputSource(removeBOM(in))); + } + + public static ReportReloadConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(ReportReloadConfig.class, new InputSource(removeBOM(reader))); + } + + public static ReportReloadConfig parse(String xml) throws SAXException, IOException { + return parseEntity(ReportReloadConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForReportPeriod(ReportPeriod parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForReportReloadConfig(ReportReloadConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_REPORT_TYPE.equals(qName)) { + ReportType reportType = m_maker.buildReportType(attributes); + + m_linker.onReportType(parentObj, reportType); + m_objs.push(reportType); + } else { + throw new SAXException(String.format("Element(%s) is not expected under report-reload-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForReportType(ReportType parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_REPORT_PERIOD.equals(qName)) { + ReportPeriod reportPeriod = m_maker.buildReportPeriod(attributes); + + m_linker.onReportPeriod(parentObj, reportPeriod); + m_objs.push(reportPeriod); + } else { + throw new SAXException(String.format("Element(%s) is not expected under report-type!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_REPORT_RELOAD_CONFIG.equals(qName)) { + ReportReloadConfig reportReloadConfig = m_maker.buildReportReloadConfig(attributes); + + m_entity = reportReloadConfig; + m_objs.push(reportReloadConfig); + m_tags.push(qName); + } else if (ENTITY_REPORT_TYPE.equals(qName)) { + ReportType reportType = m_maker.buildReportType(attributes); + + m_entity = reportType; + m_objs.push(reportType); + m_tags.push(qName); + } else if (ENTITY_REPORT_PERIOD.equals(qName)) { + ReportPeriod reportPeriod = m_maker.buildReportPeriod(attributes); + + m_entity = reportPeriod; + m_objs.push(reportPeriod); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ReportReloadConfig) { + parseForReportReloadConfig((ReportReloadConfig) parent, tag, qName, attributes); + } else if (parent instanceof ReportType) { + parseForReportType((ReportType) parent, tag, qName, attributes); + } else if (parent instanceof ReportPeriod) { + parseForReportPeriod((ReportPeriod) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..3c8b976541 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/DefaultXmlBuilder.java @@ -0,0 +1,227 @@ +package com.dianping.cat.configuration.reload.transform; + +import static com.dianping.cat.configuration.reload.Constants.ATTR_ID; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_PERIOD; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_RELOAD_CONFIG; +import static com.dianping.cat.configuration.reload.Constants.ENTITY_REPORT_TYPE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.reload.IEntity; +import com.dianping.cat.configuration.reload.IVisitor; +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitReportPeriod(ReportPeriod reportPeriod) { + startTag(ENTITY_REPORT_PERIOD, true, null, ATTR_ID, reportPeriod.getId()); + } + + @Override + public void visitReportReloadConfig(ReportReloadConfig reportReloadConfig) { + startTag(ENTITY_REPORT_RELOAD_CONFIG, null); + + if (!reportReloadConfig.getReportTypes().isEmpty()) { + for (ReportType reportType : reportReloadConfig.getReportTypes().values()) { + reportType.accept(m_visitor); + } + } + + endTag(ENTITY_REPORT_RELOAD_CONFIG); + } + + @Override + public void visitReportType(ReportType reportType) { + startTag(ENTITY_REPORT_TYPE, null, ATTR_ID, reportType.getId()); + + if (!reportType.getReportPeriods().isEmpty()) { + for (ReportPeriod reportPeriod : reportType.getReportPeriods()) { + reportPeriod.accept(m_visitor); + } + } + + endTag(ENTITY_REPORT_TYPE); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/ILinker.java new file mode 100644 index 0000000000..6ac1fbd4fa --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.configuration.reload.transform; + +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public interface ILinker { + + public boolean onReportPeriod(ReportType parent, ReportPeriod reportPeriod); + + public boolean onReportType(ReportReloadConfig parent, ReportType reportType); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IMaker.java new file mode 100644 index 0000000000..ca9ebacd44 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.reload.transform; + +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public interface IMaker { + + public ReportPeriod buildReportPeriod(T node); + + public ReportReloadConfig buildReportReloadConfig(T node); + + public ReportType buildReportType(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IParser.java new file mode 100644 index 0000000000..aceb37852b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/reload/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.reload.transform; + +import com.dianping.cat.configuration.reload.entity.ReportPeriod; +import com.dianping.cat.configuration.reload.entity.ReportReloadConfig; +import com.dianping.cat.configuration.reload.entity.ReportType; + +public interface IParser { + public ReportReloadConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForReportPeriod(IMaker maker, ILinker linker, ReportPeriod parent, T node); + + public void parseForReportType(IMaker maker, ILinker linker, ReportType parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/BaseEntity.java new file mode 100644 index 0000000000..be323f1a7d --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.server; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.server.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/Constants.java new file mode 100644 index 0000000000..259cae5e7a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/Constants.java @@ -0,0 +1,68 @@ +package com.dianping.cat.configuration.server; + +public class Constants { + + public static final String ATTR_BASE_DIR = "base-dir"; + + public static final String ATTR_DEFAULT_SERVICE_THRESHOLD = "default-service-threshold"; + + public static final String ATTR_DEFAULT_SQL_THRESHOLD = "default-sql-threshold"; + + public static final String ATTR_DEFAULT_URL_THRESHOLD = "default-url-threshold"; + + public static final String ATTR_HAR_MODE = "har-mode"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_LOCAL_BASE_DIR = "local-base-dir"; + + public static final String ATTR_LOCAL_LOGIVEW_STORAGE_TIME = "local-logivew-storage-time"; + + public static final String ATTR_LOCAL_REPORT_STORAGE_TIME = "local-report-storage-time"; + + public static final String ATTR_MAX_HDFS_STORAGE_TIME = "max-hdfs-storage-time"; + + public static final String ATTR_MAX_SIZE = "max-size"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_SERVER_URI = "server-uri"; + + public static final String ATTR_SERVICE_THRESHOLD = "service-threshold"; + + public static final String ATTR_SQL_THRESHOLD = "sql-threshold"; + + public static final String ATTR_UPLOAD_THREAD = "upload-thread"; + + public static final String ATTR_URL_THRESHOLD = "url-threshold"; + + public static final String ATTR_VALUE = "value"; + + public static final String ENTITY_CONSUMER = "consumer"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_HARFS = "harfs"; + + public static final String ENTITY_HARFSES = "harfses"; + + public static final String ENTITY_HDFS = "hdfs"; + + public static final String ENTITY_HDFSES = "hdfses"; + + public static final String ENTITY_LONG_CONFIG = "long-config"; + + public static final String ENTITY_PROPERTIES = "properties"; + + public static final String ENTITY_PROPERTY = "property"; + + public static final String ENTITY_SERVER = "server"; + + public static final String ENTITY_SERVERS = "servers"; + + public static final String ENTITY_SERVER_CONFIG = "server-config"; + + public static final String ENTITY_STORAGE = "storage"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/IEntity.java new file mode 100644 index 0000000000..c7dfa03bf1 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.server; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/IVisitor.java new file mode 100644 index 0000000000..1921825c7e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/IVisitor.java @@ -0,0 +1,32 @@ +package com.dianping.cat.configuration.server; + +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public interface IVisitor { + + public void visitConsumer(ConsumerConfig consumer); + + public void visitDomain(Domain domain); + + public void visitHarfs(HarfsConfig harfs); + + public void visitHdfs(HdfsConfig hdfs); + + public void visitLongConfig(LongConfig longConfig); + + public void visitProperty(Property property); + + public void visitServer(Server server); + + public void visitServerConfig(ServerConfig serverConfig); + + public void visitStorage(StorageConfig storage); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ConsumerConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ConsumerConfig.java new file mode 100644 index 0000000000..8e76a2c1dd --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ConsumerConfig.java @@ -0,0 +1,55 @@ +package com.dianping.cat.configuration.server.entity; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class ConsumerConfig extends BaseEntity { + private LongConfig m_longConfig; + + public ConsumerConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitConsumer(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ConsumerConfig) { + ConsumerConfig _o = (ConsumerConfig) obj; + + if (!equals(getLongConfig(), _o.getLongConfig())) { + return false; + } + + + return true; + } + + return false; + } + + public LongConfig getLongConfig() { + return m_longConfig; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_longConfig == null ? 0 : m_longConfig.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ConsumerConfig other) { + } + + public ConsumerConfig setLongConfig(LongConfig longConfig) { + m_longConfig = longConfig; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Domain.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Domain.java new file mode 100644 index 0000000000..108ca38887 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Domain.java @@ -0,0 +1,107 @@ +package com.dianping.cat.configuration.server.entity; + +import static com.dianping.cat.configuration.server.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.server.Constants.ENTITY_DOMAIN; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class Domain extends BaseEntity { + private String m_name; + + private Integer m_urlThreshold; + + private Integer m_sqlThreshold; + + private Integer m_serviceThreshold; + + public Domain() { + } + + public Domain(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public String getName() { + return m_name; + } + + public Integer getServiceThreshold() { + return m_serviceThreshold; + } + + public Integer getSqlThreshold() { + return m_sqlThreshold; + } + + public Integer getUrlThreshold() { + return m_urlThreshold; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_NAME, m_name, other.getName()); + + if (other.getUrlThreshold() != null) { + m_urlThreshold = other.getUrlThreshold(); + } + + if (other.getSqlThreshold() != null) { + m_sqlThreshold = other.getSqlThreshold(); + } + + if (other.getServiceThreshold() != null) { + m_serviceThreshold = other.getServiceThreshold(); + } + } + + public Domain setName(String name) { + m_name = name; + return this; + } + + public Domain setServiceThreshold(Integer serviceThreshold) { + m_serviceThreshold = serviceThreshold; + return this; + } + + public Domain setSqlThreshold(Integer sqlThreshold) { + m_sqlThreshold = sqlThreshold; + return this; + } + + public Domain setUrlThreshold(Integer urlThreshold) { + m_urlThreshold = urlThreshold; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HarfsConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HarfsConfig.java new file mode 100644 index 0000000000..ead72d8b50 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HarfsConfig.java @@ -0,0 +1,107 @@ +package com.dianping.cat.configuration.server.entity; + +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HARFS; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class HarfsConfig extends BaseEntity { + private String m_id; + + private String m_maxSize = "128M"; + + private String m_serverUri; + + private String m_baseDir; + + public HarfsConfig() { + } + + public HarfsConfig(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitHarfs(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HarfsConfig) { + HarfsConfig _o = (HarfsConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getBaseDir() { + return m_baseDir; + } + + public String getId() { + return m_id; + } + + public String getMaxSize() { + return m_maxSize; + } + + public String getServerUri() { + return m_serverUri; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(HarfsConfig other) { + assertAttributeEquals(other, ENTITY_HARFS, ATTR_ID, m_id, other.getId()); + + if (other.getMaxSize() != null) { + m_maxSize = other.getMaxSize(); + } + + if (other.getServerUri() != null) { + m_serverUri = other.getServerUri(); + } + + if (other.getBaseDir() != null) { + m_baseDir = other.getBaseDir(); + } + } + + public HarfsConfig setBaseDir(String baseDir) { + m_baseDir = baseDir; + return this; + } + + public HarfsConfig setId(String id) { + m_id = id; + return this; + } + + public HarfsConfig setMaxSize(String maxSize) { + m_maxSize = maxSize; + return this; + } + + public HarfsConfig setServerUri(String serverUri) { + m_serverUri = serverUri; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HdfsConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HdfsConfig.java new file mode 100644 index 0000000000..a8b7835035 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/HdfsConfig.java @@ -0,0 +1,107 @@ +package com.dianping.cat.configuration.server.entity; + +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HDFS; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class HdfsConfig extends BaseEntity { + private String m_id; + + private String m_maxSize = "128M"; + + private String m_serverUri; + + private String m_baseDir; + + public HdfsConfig() { + } + + public HdfsConfig(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitHdfs(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HdfsConfig) { + HdfsConfig _o = (HdfsConfig) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getBaseDir() { + return m_baseDir; + } + + public String getId() { + return m_id; + } + + public String getMaxSize() { + return m_maxSize; + } + + public String getServerUri() { + return m_serverUri; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(HdfsConfig other) { + assertAttributeEquals(other, ENTITY_HDFS, ATTR_ID, m_id, other.getId()); + + if (other.getMaxSize() != null) { + m_maxSize = other.getMaxSize(); + } + + if (other.getServerUri() != null) { + m_serverUri = other.getServerUri(); + } + + if (other.getBaseDir() != null) { + m_baseDir = other.getBaseDir(); + } + } + + public HdfsConfig setBaseDir(String baseDir) { + m_baseDir = baseDir; + return this; + } + + public HdfsConfig setId(String id) { + m_id = id; + return this; + } + + public HdfsConfig setMaxSize(String maxSize) { + m_maxSize = maxSize; + return this; + } + + public HdfsConfig setServerUri(String serverUri) { + m_serverUri = serverUri; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/LongConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/LongConfig.java new file mode 100644 index 0000000000..8a8d2b3dea --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/LongConfig.java @@ -0,0 +1,119 @@ +package com.dianping.cat.configuration.server.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class LongConfig extends BaseEntity { + private int m_defaultUrlThreshold = 1000; + + private int m_defaultSqlThreshold = 100; + + private Map m_domains = new LinkedHashMap(); + + private int m_defaultServiceThreshold = 50; + + public LongConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitLongConfig(this); + } + + public LongConfig addDomain(Domain domain) { + m_domains.put(domain.getName(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof LongConfig) { + LongConfig _o = (LongConfig) obj; + + if (getDefaultUrlThreshold() != _o.getDefaultUrlThreshold()) { + return false; + } + + if (getDefaultSqlThreshold() != _o.getDefaultSqlThreshold()) { + return false; + } + + if (!equals(getDomains(), _o.getDomains())) { + return false; + } + + if (getDefaultServiceThreshold() != _o.getDefaultServiceThreshold()) { + return false; + } + + + return true; + } + + return false; + } + + public Domain findDomain(String name) { + return m_domains.get(name); + } + + public int getDefaultServiceThreshold() { + return m_defaultServiceThreshold; + } + + public int getDefaultSqlThreshold() { + return m_defaultSqlThreshold; + } + + public int getDefaultUrlThreshold() { + return m_defaultUrlThreshold; + } + + public Map getDomains() { + return m_domains; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + m_defaultUrlThreshold; + hash = hash * 31 + m_defaultSqlThreshold; + hash = hash * 31 + (m_domains == null ? 0 : m_domains.hashCode()); + hash = hash * 31 + m_defaultServiceThreshold; + + return hash; + } + + @Override + public void mergeAttributes(LongConfig other) { + m_defaultUrlThreshold = other.getDefaultUrlThreshold(); + + m_defaultSqlThreshold = other.getDefaultSqlThreshold(); + + m_defaultServiceThreshold = other.getDefaultServiceThreshold(); + } + + public Domain removeDomain(String name) { + return m_domains.remove(name); + } + + public LongConfig setDefaultServiceThreshold(int defaultServiceThreshold) { + m_defaultServiceThreshold = defaultServiceThreshold; + return this; + } + + public LongConfig setDefaultSqlThreshold(int defaultSqlThreshold) { + m_defaultSqlThreshold = defaultSqlThreshold; + return this; + } + + public LongConfig setDefaultUrlThreshold(int defaultUrlThreshold) { + m_defaultUrlThreshold = defaultUrlThreshold; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Property.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Property.java new file mode 100644 index 0000000000..d8896ed7c8 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Property.java @@ -0,0 +1,77 @@ +package com.dianping.cat.configuration.server.entity; + +import static com.dianping.cat.configuration.server.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTY; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class Property extends BaseEntity { + private String m_name; + + private String m_value; + + public Property() { + } + + public Property(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitProperty(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Property) { + Property _o = (Property) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public String getName() { + return m_name; + } + + public String getValue() { + return m_value; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Property other) { + assertAttributeEquals(other, ENTITY_PROPERTY, ATTR_NAME, m_name, other.getName()); + + if (other.getValue() != null) { + m_value = other.getValue(); + } + } + + public Property setName(String name) { + m_name = name; + return this; + } + + public Property setValue(String value) { + m_value = value; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Server.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Server.java new file mode 100644 index 0000000000..b0f5131a96 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/Server.java @@ -0,0 +1,107 @@ +package com.dianping.cat.configuration.server.entity; + +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class Server extends BaseEntity { + private String m_id; + + private Map m_properties = new LinkedHashMap(); + + private StorageConfig m_storage; + + private ConsumerConfig m_consumer; + + public Server() { + } + + public Server(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitServer(this); + } + + public Server addProperty(Property property) { + m_properties.put(property.getName(), property); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Server) { + Server _o = (Server) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Property findProperty(String name) { + return m_properties.get(name); + } + + public ConsumerConfig getConsumer() { + return m_consumer; + } + + public String getId() { + return m_id; + } + + public Map getProperties() { + return m_properties; + } + + public StorageConfig getStorage() { + return m_storage; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Server other) { + assertAttributeEquals(other, ENTITY_SERVER, ATTR_ID, m_id, other.getId()); + + } + + public Property removeProperty(String name) { + return m_properties.remove(name); + } + + public Server setConsumer(ConsumerConfig consumer) { + m_consumer = consumer; + return this; + } + + public Server setId(String id) { + m_id = id; + return this; + } + + public Server setStorage(StorageConfig storage) { + m_storage = storage; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ServerConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ServerConfig.java new file mode 100644 index 0000000000..74c438033a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/ServerConfig.java @@ -0,0 +1,66 @@ +package com.dianping.cat.configuration.server.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class ServerConfig extends BaseEntity { + private Map m_servers = new LinkedHashMap(); + + public ServerConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitServerConfig(this); + } + + public ServerConfig addServer(Server server) { + m_servers.put(server.getId(), server); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ServerConfig) { + ServerConfig _o = (ServerConfig) obj; + + if (!equals(getServers(), _o.getServers())) { + return false; + } + + + return true; + } + + return false; + } + + public Server findServer(String id) { + return m_servers.get(id); + } + + public Map getServers() { + return m_servers; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_servers == null ? 0 : m_servers.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ServerConfig other) { + } + + public Server removeServer(String id) { + return m_servers.remove(id); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/StorageConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/StorageConfig.java new file mode 100644 index 0000000000..edbd64e87a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/entity/StorageConfig.java @@ -0,0 +1,227 @@ +package com.dianping.cat.configuration.server.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.server.BaseEntity; +import com.dianping.cat.configuration.server.IVisitor; + +public class StorageConfig extends BaseEntity { + private String m_localBaseDir = "target/bucket"; + + private int m_maxHdfsStorageTime = 15; + + private int m_localReportStorageTime = 3; + + private int m_localLogivewStorageTime = 7; + + private boolean m_harMode = true; + + private Map m_hdfses = new LinkedHashMap(); + + private Map m_harfses = new LinkedHashMap(); + + private Map m_properties = new LinkedHashMap(); + + private int m_uploadThread = 5; + + public StorageConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitStorage(this); + } + + public StorageConfig addHarfs(HarfsConfig harfs) { + m_harfses.put(harfs.getId(), harfs); + return this; + } + + public StorageConfig addHdfs(HdfsConfig hdfs) { + m_hdfses.put(hdfs.getId(), hdfs); + return this; + } + + public StorageConfig addProperty(Property property) { + m_properties.put(property.getName(), property); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof StorageConfig) { + StorageConfig _o = (StorageConfig) obj; + + if (!equals(getLocalBaseDir(), _o.getLocalBaseDir())) { + return false; + } + + if (getMaxHdfsStorageTime() != _o.getMaxHdfsStorageTime()) { + return false; + } + + if (getLocalReportStorageTime() != _o.getLocalReportStorageTime()) { + return false; + } + + if (getLocalLogivewStorageTime() != _o.getLocalLogivewStorageTime()) { + return false; + } + + if (getHarMode() != _o.getHarMode()) { + return false; + } + + if (!equals(getHdfses(), _o.getHdfses())) { + return false; + } + + if (!equals(getHarfses(), _o.getHarfses())) { + return false; + } + + if (!equals(getProperties(), _o.getProperties())) { + return false; + } + + if (getUploadThread() != _o.getUploadThread()) { + return false; + } + + + return true; + } + + return false; + } + + public HarfsConfig findHarfs(String id) { + return m_harfses.get(id); + } + + public HdfsConfig findHdfs(String id) { + return m_hdfses.get(id); + } + + public Property findProperty(String name) { + return m_properties.get(name); + } + + public Map getHarfses() { + return m_harfses; + } + + public boolean getHarMode() { + return m_harMode; + } + + public Map getHdfses() { + return m_hdfses; + } + + public String getLocalBaseDir() { + return m_localBaseDir; + } + + public int getLocalLogivewStorageTime() { + return m_localLogivewStorageTime; + } + + public int getLocalReportStorageTime() { + return m_localReportStorageTime; + } + + public int getMaxHdfsStorageTime() { + return m_maxHdfsStorageTime; + } + + public Map getProperties() { + return m_properties; + } + + public int getUploadThread() { + return m_uploadThread; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_localBaseDir == null ? 0 : m_localBaseDir.hashCode()); + hash = hash * 31 + m_maxHdfsStorageTime; + hash = hash * 31 + m_localReportStorageTime; + hash = hash * 31 + m_localLogivewStorageTime; + hash = hash * 31 + (m_harMode ? 1 : 0); + hash = hash * 31 + (m_hdfses == null ? 0 : m_hdfses.hashCode()); + hash = hash * 31 + (m_harfses == null ? 0 : m_harfses.hashCode()); + hash = hash * 31 + (m_properties == null ? 0 : m_properties.hashCode()); + hash = hash * 31 + m_uploadThread; + + return hash; + } + + public boolean isHarMode() { + return m_harMode; + } + + @Override + public void mergeAttributes(StorageConfig other) { + if (other.getLocalBaseDir() != null) { + m_localBaseDir = other.getLocalBaseDir(); + } + + m_maxHdfsStorageTime = other.getMaxHdfsStorageTime(); + + m_localReportStorageTime = other.getLocalReportStorageTime(); + + m_localLogivewStorageTime = other.getLocalLogivewStorageTime(); + + m_harMode = other.getHarMode(); + + m_uploadThread = other.getUploadThread(); + } + + public HarfsConfig removeHarfs(String id) { + return m_harfses.remove(id); + } + + public HdfsConfig removeHdfs(String id) { + return m_hdfses.remove(id); + } + + public Property removeProperty(String name) { + return m_properties.remove(name); + } + + public StorageConfig setHarMode(boolean harMode) { + m_harMode = harMode; + return this; + } + + public StorageConfig setLocalBaseDir(String localBaseDir) { + m_localBaseDir = localBaseDir; + return this; + } + + public StorageConfig setLocalLogivewStorageTime(int localLogivewStorageTime) { + m_localLogivewStorageTime = localLogivewStorageTime; + return this; + } + + public StorageConfig setLocalReportStorageTime(int localReportStorageTime) { + m_localReportStorageTime = localReportStorageTime; + return this; + } + + public StorageConfig setMaxHdfsStorageTime(int maxHdfsStorageTime) { + m_maxHdfsStorageTime = maxHdfsStorageTime; + return this; + } + + public StorageConfig setUploadThread(int uploadThread) { + m_uploadThread = uploadThread; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/BaseEntity.java new file mode 100644 index 0000000000..759719630f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.server.filter; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.server.filter.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/Constants.java new file mode 100644 index 0000000000..b86d05a3d5 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/Constants.java @@ -0,0 +1,32 @@ +package com.dianping.cat.configuration.server.filter; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ATTR_MATCH_TYPES = "match-types"; + + public static final String ATTR_START_TYPES = "start-types"; + + public static final String ATTR_TITLE = "title"; + + public static final String ELEMENT_DOMAIN = "domain"; + + public static final String ELEMENT_DOMAINS = "domains"; + + public static final String ELEMENT_TRANSACTION_NAME = "transaction-name"; + + public static final String ELEMENT_TRANSACTION_NAMES = "transaction-names"; + + public static final String ELEMENT_TRANSACTION_TYPE = "transaction-type"; + + public static final String ELEMENT_TRANSACTION_TYPES = "transaction-types"; + + public static final String ENTITY_ATOMIC_TREE_CONFIG = "atomic-tree-config"; + + public static final String ENTITY_CRASH_LOG_DOMAIN = "crash-log-domain"; + + public static final String ENTITY_CRASH_LOG_DOMAINS = "crash-log-domains"; + + public static final String ENTITY_SERVER_FILTER_CONFIG = "server-filter-config"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IEntity.java new file mode 100644 index 0000000000..9db0c10192 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.server.filter; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IVisitor.java new file mode 100644 index 0000000000..f99880ed44 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.server.filter; + +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public interface IVisitor { + + public void visitAtomicTreeConfig(AtomicTreeConfig atomicTreeConfig); + + public void visitCrashLogDomain(CrashLogDomain crashLogDomain); + + public void visitServerFilterConfig(ServerFilterConfig serverFilterConfig); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/AtomicTreeConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/AtomicTreeConfig.java new file mode 100644 index 0000000000..08d73fbec7 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/AtomicTreeConfig.java @@ -0,0 +1,78 @@ +package com.dianping.cat.configuration.server.filter.entity; + +import com.dianping.cat.configuration.server.filter.BaseEntity; +import com.dianping.cat.configuration.server.filter.IVisitor; + +public class AtomicTreeConfig extends BaseEntity { + private String m_startTypes; + + private String m_matchTypes; + + public AtomicTreeConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitAtomicTreeConfig(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AtomicTreeConfig) { + AtomicTreeConfig _o = (AtomicTreeConfig) obj; + + if (!equals(getStartTypes(), _o.getStartTypes())) { + return false; + } + + if (!equals(getMatchTypes(), _o.getMatchTypes())) { + return false; + } + + + return true; + } + + return false; + } + + public String getMatchTypes() { + return m_matchTypes; + } + + public String getStartTypes() { + return m_startTypes; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_startTypes == null ? 0 : m_startTypes.hashCode()); + hash = hash * 31 + (m_matchTypes == null ? 0 : m_matchTypes.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(AtomicTreeConfig other) { + if (other.getStartTypes() != null) { + m_startTypes = other.getStartTypes(); + } + + if (other.getMatchTypes() != null) { + m_matchTypes = other.getMatchTypes(); + } + } + + public AtomicTreeConfig setMatchTypes(String matchTypes) { + m_matchTypes = matchTypes; + return this; + } + + public AtomicTreeConfig setStartTypes(String startTypes) { + m_startTypes = startTypes; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/CrashLogDomain.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/CrashLogDomain.java new file mode 100644 index 0000000000..2baff8dddf --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/CrashLogDomain.java @@ -0,0 +1,77 @@ +package com.dianping.cat.configuration.server.filter.entity; + +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_CRASH_LOG_DOMAIN; + +import com.dianping.cat.configuration.server.filter.BaseEntity; +import com.dianping.cat.configuration.server.filter.IVisitor; + +public class CrashLogDomain extends BaseEntity { + private String m_id; + + private String m_title; + + public CrashLogDomain() { + } + + public CrashLogDomain(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCrashLogDomain(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CrashLogDomain) { + CrashLogDomain _o = (CrashLogDomain) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public String getTitle() { + return m_title; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(CrashLogDomain other) { + assertAttributeEquals(other, ENTITY_CRASH_LOG_DOMAIN, ATTR_ID, m_id, other.getId()); + + if (other.getTitle() != null) { + m_title = other.getTitle(); + } + } + + public CrashLogDomain setId(String id) { + m_id = id; + return this; + } + + public CrashLogDomain setTitle(String title) { + m_title = title; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/ServerFilterConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/ServerFilterConfig.java new file mode 100644 index 0000000000..073cd1870a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/entity/ServerFilterConfig.java @@ -0,0 +1,141 @@ +package com.dianping.cat.configuration.server.filter.entity; + +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import com.dianping.cat.configuration.server.filter.BaseEntity; +import com.dianping.cat.configuration.server.filter.IVisitor; + +public class ServerFilterConfig extends BaseEntity { + private Set m_transactionTypes = new LinkedHashSet(); + + private Set m_transactionNames = new LinkedHashSet(); + + private Set m_domains = new LinkedHashSet(); + + private Map m_crashLogDomains = new LinkedHashMap(); + + private AtomicTreeConfig m_atomicTreeConfig; + + public ServerFilterConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitServerFilterConfig(this); + } + + public ServerFilterConfig addCrashLogDomain(CrashLogDomain crashLogDomain) { + m_crashLogDomains.put(crashLogDomain.getId(), crashLogDomain); + return this; + } + + public ServerFilterConfig addDomain(String domain) { + m_domains.add(domain); + return this; + } + + public ServerFilterConfig addTransactionName(String transactionName) { + m_transactionNames.add(transactionName); + return this; + } + + public ServerFilterConfig addTransactionType(String transactionType) { + m_transactionTypes.add(transactionType); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ServerFilterConfig) { + ServerFilterConfig _o = (ServerFilterConfig) obj; + + if (!equals(getTransactionTypes(), _o.getTransactionTypes())) { + return false; + } + + if (!equals(getTransactionNames(), _o.getTransactionNames())) { + return false; + } + + if (!equals(getDomains(), _o.getDomains())) { + return false; + } + + if (!equals(getCrashLogDomains(), _o.getCrashLogDomains())) { + return false; + } + + if (!equals(getAtomicTreeConfig(), _o.getAtomicTreeConfig())) { + return false; + } + + + return true; + } + + return false; + } + + public CrashLogDomain findCrashLogDomain(String id) { + return m_crashLogDomains.get(id); + } + + public AtomicTreeConfig getAtomicTreeConfig() { + return m_atomicTreeConfig; + } + + public Map getCrashLogDomains() { + return m_crashLogDomains; + } + + public Set getDomains() { + return m_domains; + } + + public Set getTransactionNames() { + return m_transactionNames; + } + + public Set getTransactionTypes() { + return m_transactionTypes; + } + + @Override + public int hashCode() { + int hash = 0; + + for (String e : m_transactionTypes) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + for (String e : m_transactionNames) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + for (String e : m_domains) { + hash = hash * 31 + (e == null ? 0 :e.hashCode()); + } + + hash = hash * 31 + (m_crashLogDomains == null ? 0 : m_crashLogDomains.hashCode()); + hash = hash * 31 + (m_atomicTreeConfig == null ? 0 : m_atomicTreeConfig.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(ServerFilterConfig other) { + } + + public CrashLogDomain removeCrashLogDomain(String id) { + return m_crashLogDomains.remove(id); + } + + public ServerFilterConfig setAtomicTreeConfig(AtomicTreeConfig atomicTreeConfig) { + m_atomicTreeConfig = atomicTreeConfig; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultLinker.java new file mode 100644 index 0000000000..6e173db914 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultLinker.java @@ -0,0 +1,45 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onAtomicTreeConfig(final ServerFilterConfig parent, final AtomicTreeConfig atomicTreeConfig) { + parent.setAtomicTreeConfig(atomicTreeConfig); + return true; + } + + @Override + public boolean onCrashLogDomain(final ServerFilterConfig parent, final CrashLogDomain crashLogDomain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addCrashLogDomain(crashLogDomain); + } + }); + } else { + parent.addCrashLogDomain(crashLogDomain); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..0a405e8bf9 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxMaker.java @@ -0,0 +1,94 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_MATCH_TYPES; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_START_TYPES; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_TITLE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public AtomicTreeConfig buildAtomicTreeConfig(Attributes attributes) { + String startTypes = attributes.getValue(ATTR_START_TYPES); + String matchTypes = attributes.getValue(ATTR_MATCH_TYPES); + AtomicTreeConfig atomicTreeConfig = new AtomicTreeConfig(); + + if (startTypes != null) { + atomicTreeConfig.setStartTypes(startTypes); + } + + if (matchTypes != null) { + atomicTreeConfig.setMatchTypes(matchTypes); + } + + return atomicTreeConfig; + } + + @Override + public CrashLogDomain buildCrashLogDomain(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String title = attributes.getValue(ATTR_TITLE); + CrashLogDomain crashLogDomain = new CrashLogDomain(id); + + if (title != null) { + crashLogDomain.setTitle(title); + } + + return crashLogDomain; + } + + @Override + public String buildDomain(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public ServerFilterConfig buildServerFilterConfig(Attributes attributes) { + ServerFilterConfig serverFilterConfig = new ServerFilterConfig(); + + return serverFilterConfig; + } + + @Override + public String buildTransactionName(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @Override + public String buildTransactionType(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..aa1eaf3dc8 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultSaxParser.java @@ -0,0 +1,267 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_DOMAINS; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_NAME; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_NAMES; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_TYPE; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_TYPES; + +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_ATOMIC_TREE_CONFIG; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_CRASH_LOG_DOMAIN; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_SERVER_FILTER_CONFIG; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.server.filter.IEntity; +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static ServerFilterConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(ServerFilterConfig.class, new InputSource(removeBOM(in))); + } + + public static ServerFilterConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(ServerFilterConfig.class, new InputSource(removeBOM(reader))); + } + + public static ServerFilterConfig parse(String xml) throws SAXException, IOException { + return parseEntity(ServerFilterConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof ServerFilterConfig) { + ServerFilterConfig serverFilterConfig = (ServerFilterConfig) currentObj; + + if (ELEMENT_TRANSACTION_TYPE.equals(currentTag)) { + serverFilterConfig.addTransactionType(getText()); + } else if (ELEMENT_TRANSACTION_NAME.equals(currentTag)) { + serverFilterConfig.addTransactionName(getText()); + } else if (ELEMENT_DOMAIN.equals(currentTag)) { + serverFilterConfig.addDomain(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForAtomicTreeConfig(AtomicTreeConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForCrashLogDomain(CrashLogDomain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForServerFilterConfig(ServerFilterConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_TRANSACTION_TYPES.equals(qName) || ELEMENT_TRANSACTION_TYPE.equals(qName) || ELEMENT_TRANSACTION_NAMES.equals(qName) || ELEMENT_TRANSACTION_NAME.equals(qName) || ELEMENT_DOMAINS.equals(qName) || ELEMENT_DOMAIN.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_CRASH_LOG_DOMAIN.equals(qName)) { + CrashLogDomain crashLogDomain = m_maker.buildCrashLogDomain(attributes); + + m_linker.onCrashLogDomain(parentObj, crashLogDomain); + m_objs.push(crashLogDomain); + } else if (ENTITY_ATOMIC_TREE_CONFIG.equals(qName)) { + AtomicTreeConfig atomicTreeConfig = m_maker.buildAtomicTreeConfig(attributes); + + m_linker.onAtomicTreeConfig(parentObj, atomicTreeConfig); + m_objs.push(atomicTreeConfig); + } else { + throw new SAXException(String.format("Element(%s) is not expected under server-filter-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_SERVER_FILTER_CONFIG.equals(qName)) { + ServerFilterConfig serverFilterConfig = m_maker.buildServerFilterConfig(attributes); + + m_entity = serverFilterConfig; + m_objs.push(serverFilterConfig); + m_tags.push(qName); + } else if (ENTITY_CRASH_LOG_DOMAIN.equals(qName)) { + CrashLogDomain crashLogDomain = m_maker.buildCrashLogDomain(attributes); + + m_entity = crashLogDomain; + m_objs.push(crashLogDomain); + m_tags.push(qName); + } else if (ENTITY_ATOMIC_TREE_CONFIG.equals(qName)) { + AtomicTreeConfig atomicTreeConfig = m_maker.buildAtomicTreeConfig(attributes); + + m_entity = atomicTreeConfig; + m_objs.push(atomicTreeConfig); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ServerFilterConfig) { + parseForServerFilterConfig((ServerFilterConfig) parent, tag, qName, attributes); + } else if (parent instanceof CrashLogDomain) { + parseForCrashLogDomain((CrashLogDomain) parent, tag, qName, attributes); + } else if (parent instanceof AtomicTreeConfig) { + parseForAtomicTreeConfig((AtomicTreeConfig) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultValidator.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultValidator.java new file mode 100644 index 0000000000..20ca57f05b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultValidator.java @@ -0,0 +1,85 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_CRASH_LOG_DOMAIN; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_SERVER_FILTER_CONFIG; + +import java.util.Stack; + +import com.dianping.cat.configuration.server.filter.IVisitor; +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public class DefaultValidator implements IVisitor { + + private Path m_path = new Path(); + + protected void assertRequired(String name, Object value) { + if (value == null) { + throw new RuntimeException(String.format("%s at path(%s) is required!", name, m_path)); + } + } + + @Override + public void visitAtomicTreeConfig(AtomicTreeConfig atomicTreeConfig) { + } + + @Override + public void visitCrashLogDomain(CrashLogDomain crashLogDomain) { + m_path.down(ENTITY_CRASH_LOG_DOMAIN); + + assertRequired(ATTR_ID, crashLogDomain.getId()); + + m_path.up(ENTITY_CRASH_LOG_DOMAIN); + } + + @Override + public void visitServerFilterConfig(ServerFilterConfig serverFilterConfig) { + m_path.down(ENTITY_SERVER_FILTER_CONFIG); + + visitServerFilterConfigChildren(serverFilterConfig); + + m_path.up(ENTITY_SERVER_FILTER_CONFIG); + } + + protected void visitServerFilterConfigChildren(ServerFilterConfig serverFilterConfig) { + for (CrashLogDomain crashLogDomain : serverFilterConfig.getCrashLogDomains().values()) { + visitCrashLogDomain(crashLogDomain); + } + + if (serverFilterConfig.getAtomicTreeConfig() != null) { + visitAtomicTreeConfig(serverFilterConfig.getAtomicTreeConfig()); + } + } + + static class Path { + private Stack m_sections = new Stack(); + + public Path down(String nextSection) { + m_sections.push(nextSection); + + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (String section : m_sections) { + sb.append('/').append(section); + } + + return sb.toString(); + } + + public Path up(String currentSection) { + if (m_sections.isEmpty() || !m_sections.peek().equals(currentSection)) { + throw new RuntimeException("INTERNAL ERROR: stack mismatched!"); + } + + m_sections.pop(); + return this; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..9bfe37adba --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/DefaultXmlBuilder.java @@ -0,0 +1,290 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_MATCH_TYPES; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_START_TYPES; +import static com.dianping.cat.configuration.server.filter.Constants.ATTR_TITLE; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_DOMAIN; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_NAME; +import static com.dianping.cat.configuration.server.filter.Constants.ELEMENT_TRANSACTION_TYPE; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_ATOMIC_TREE_CONFIG; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_CRASH_LOG_DOMAIN; +import static com.dianping.cat.configuration.server.filter.Constants.ENTITY_SERVER_FILTER_CONFIG; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.server.filter.IEntity; +import com.dianping.cat.configuration.server.filter.IVisitor; +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + @Override + public void visitAtomicTreeConfig(AtomicTreeConfig atomicTreeConfig) { + startTag(ENTITY_ATOMIC_TREE_CONFIG, true, null, ATTR_START_TYPES, atomicTreeConfig.getStartTypes(), ATTR_MATCH_TYPES, atomicTreeConfig.getMatchTypes()); + } + + @Override + public void visitCrashLogDomain(CrashLogDomain crashLogDomain) { + startTag(ENTITY_CRASH_LOG_DOMAIN, true, null, ATTR_ID, crashLogDomain.getId(), ATTR_TITLE, crashLogDomain.getTitle()); + } + + @Override + public void visitServerFilterConfig(ServerFilterConfig serverFilterConfig) { + startTag(ENTITY_SERVER_FILTER_CONFIG, null); + + if (!serverFilterConfig.getTransactionTypes().isEmpty()) { + for (String transactionType : serverFilterConfig.getTransactionTypes()) { + tagWithText(ELEMENT_TRANSACTION_TYPE, transactionType); + } + } + + if (!serverFilterConfig.getTransactionNames().isEmpty()) { + for (String transactionName : serverFilterConfig.getTransactionNames()) { + tagWithText(ELEMENT_TRANSACTION_NAME, transactionName); + } + } + + if (!serverFilterConfig.getDomains().isEmpty()) { + for (String domain : serverFilterConfig.getDomains()) { + tagWithText(ELEMENT_DOMAIN, domain); + } + } + + if (!serverFilterConfig.getCrashLogDomains().isEmpty()) { + for (CrashLogDomain crashLogDomain : serverFilterConfig.getCrashLogDomains().values()) { + crashLogDomain.accept(m_visitor); + } + } + + if (serverFilterConfig.getAtomicTreeConfig() != null) { + serverFilterConfig.getAtomicTreeConfig().accept(m_visitor); + } + + endTag(ENTITY_SERVER_FILTER_CONFIG); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/ILinker.java new file mode 100644 index 0000000000..a3e2d44445 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public interface ILinker { + + public boolean onAtomicTreeConfig(ServerFilterConfig parent, AtomicTreeConfig atomicTreeConfig); + + public boolean onCrashLogDomain(ServerFilterConfig parent, CrashLogDomain crashLogDomain); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IMaker.java new file mode 100644 index 0000000000..e45894324c --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IMaker.java @@ -0,0 +1,20 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public interface IMaker { + + public AtomicTreeConfig buildAtomicTreeConfig(T node); + + public CrashLogDomain buildCrashLogDomain(T node); + + public String buildDomain(T node); + + public ServerFilterConfig buildServerFilterConfig(T node); + + public String buildTransactionName(T node); + + public String buildTransactionType(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IParser.java new file mode 100644 index 0000000000..72e6b4ef2f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/filter/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.server.filter.transform; + +import com.dianping.cat.configuration.server.filter.entity.AtomicTreeConfig; +import com.dianping.cat.configuration.server.filter.entity.CrashLogDomain; +import com.dianping.cat.configuration.server.filter.entity.ServerFilterConfig; + +public interface IParser { + public ServerFilterConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForAtomicTreeConfig(IMaker maker, ILinker linker, AtomicTreeConfig parent, T node); + + public void parseForCrashLogDomain(IMaker maker, ILinker linker, CrashLogDomain parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/BaseVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/BaseVisitor.java new file mode 100644 index 0000000000..50478ed2fe --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/BaseVisitor.java @@ -0,0 +1,81 @@ +package com.dianping.cat.configuration.server.transform; + +import com.dianping.cat.configuration.server.IVisitor; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitConsumer(ConsumerConfig consumer) { + if (consumer.getLongConfig() != null) { + visitLongConfig(consumer.getLongConfig()); + } + } + + @Override + public void visitDomain(Domain domain) { + } + + @Override + public void visitHarfs(HarfsConfig harfs) { + } + + @Override + public void visitHdfs(HdfsConfig hdfs) { + } + + @Override + public void visitLongConfig(LongConfig longConfig) { + for (Domain domain : longConfig.getDomains().values()) { + visitDomain(domain); + } + } + + @Override + public void visitProperty(Property property) { + } + + @Override + public void visitServer(Server server) { + for (Property property : server.getProperties().values()) { + visitProperty(property); + } + + if (server.getStorage() != null) { + visitStorage(server.getStorage()); + } + + if (server.getConsumer() != null) { + visitConsumer(server.getConsumer()); + } + } + + @Override + public void visitServerConfig(ServerConfig serverConfig) { + for (Server server : serverConfig.getServers().values()) { + visitServer(server); + } + } + + @Override + public void visitStorage(StorageConfig storage) { + for (HdfsConfig hdfs : storage.getHdfses().values()) { + visitHdfs(hdfs); + } + + for (HarfsConfig harfs : storage.getHarfses().values()) { + visitHarfs(harfs); + } + + for (Property property : storage.getProperties().values()) { + visitProperty(property); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultLinker.java new file mode 100644 index 0000000000..58b9dde1f7 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultLinker.java @@ -0,0 +1,143 @@ +package com.dianping.cat.configuration.server.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onConsumer(final Server parent, final ConsumerConfig consumer) { + parent.setConsumer(consumer); + return true; + } + + @Override + public boolean onDomain(final LongConfig parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } + + @Override + public boolean onHarfs(final StorageConfig parent, final HarfsConfig harfs) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addHarfs(harfs); + } + }); + } else { + parent.addHarfs(harfs); + } + + return true; + } + + @Override + public boolean onHdfs(final StorageConfig parent, final HdfsConfig hdfs) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addHdfs(hdfs); + } + }); + } else { + parent.addHdfs(hdfs); + } + + return true; + } + + @Override + public boolean onLongConfig(final ConsumerConfig parent, final LongConfig longConfig) { + parent.setLongConfig(longConfig); + return true; + } + + @Override + public boolean onProperty(final Server parent, final Property property) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addProperty(property); + } + }); + } else { + parent.addProperty(property); + } + + return true; + } + + @Override + public boolean onProperty(final StorageConfig parent, final Property property) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addProperty(property); + } + }); + } else { + parent.addProperty(property); + } + + return true; + } + + @Override + public boolean onServer(final ServerConfig parent, final Server server) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addServer(server); + } + }); + } else { + parent.addServer(server); + } + + return true; + } + + @Override + public boolean onStorage(final Server parent, final StorageConfig storage) { + parent.setStorage(storage); + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultMerger.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultMerger.java new file mode 100644 index 0000000000..3702ab946e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultMerger.java @@ -0,0 +1,291 @@ +package com.dianping.cat.configuration.server.transform; + +import java.util.Stack; + +import com.dianping.cat.configuration.server.IEntity; +import com.dianping.cat.configuration.server.IVisitor; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private ServerConfig m_serverConfig; + + public DefaultMerger() { + } + + public DefaultMerger(ServerConfig serverConfig) { + m_serverConfig = serverConfig; + m_objs.push(serverConfig); + } + + public ServerConfig getServerConfig() { + return m_serverConfig; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeConsumer(ConsumerConfig to, ConsumerConfig from) { + to.mergeAttributes(from); + } + + protected void mergeDomain(Domain to, Domain from) { + to.mergeAttributes(from); + } + + protected void mergeHarfs(HarfsConfig to, HarfsConfig from) { + to.mergeAttributes(from); + } + + protected void mergeHdfs(HdfsConfig to, HdfsConfig from) { + to.mergeAttributes(from); + } + + protected void mergeLongConfig(LongConfig to, LongConfig from) { + to.mergeAttributes(from); + } + + protected void mergeProperty(Property to, Property from) { + to.mergeAttributes(from); + } + + protected void mergeServer(Server to, Server from) { + to.mergeAttributes(from); + } + + protected void mergeServerConfig(ServerConfig to, ServerConfig from) { + to.mergeAttributes(from); + } + + protected void mergeStorage(StorageConfig to, StorageConfig from) { + to.mergeAttributes(from); + } + + @Override + public void visitConsumer(ConsumerConfig from) { + ConsumerConfig to = (ConsumerConfig) m_objs.peek(); + + mergeConsumer(to, from); + visitConsumerChildren(to, from); + } + + protected void visitConsumerChildren(ConsumerConfig to, ConsumerConfig from) { + if (from.getLongConfig() != null) { + LongConfig target = to.getLongConfig(); + + if (target == null) { + target = new LongConfig(); + to.setLongConfig(target); + } + + m_objs.push(target); + from.getLongConfig().accept(this); + m_objs.pop(); + } + } + + @Override + public void visitDomain(Domain from) { + Domain to = (Domain) m_objs.peek(); + + mergeDomain(to, from); + visitDomainChildren(to, from); + } + + protected void visitDomainChildren(Domain to, Domain from) { + } + + @Override + public void visitHarfs(HarfsConfig from) { + HarfsConfig to = (HarfsConfig) m_objs.peek(); + + mergeHarfs(to, from); + visitHarfsChildren(to, from); + } + + protected void visitHarfsChildren(HarfsConfig to, HarfsConfig from) { + } + + @Override + public void visitHdfs(HdfsConfig from) { + HdfsConfig to = (HdfsConfig) m_objs.peek(); + + mergeHdfs(to, from); + visitHdfsChildren(to, from); + } + + protected void visitHdfsChildren(HdfsConfig to, HdfsConfig from) { + } + + @Override + public void visitLongConfig(LongConfig from) { + LongConfig to = (LongConfig) m_objs.peek(); + + mergeLongConfig(to, from); + visitLongConfigChildren(to, from); + } + + protected void visitLongConfigChildren(LongConfig to, LongConfig from) { + for (Domain source : from.getDomains().values()) { + Domain target = to.findDomain(source.getName()); + + if (target == null) { + target = new Domain(source.getName()); + to.addDomain(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitProperty(Property from) { + Property to = (Property) m_objs.peek(); + + mergeProperty(to, from); + visitPropertyChildren(to, from); + } + + protected void visitPropertyChildren(Property to, Property from) { + } + + @Override + public void visitServer(Server from) { + Server to = (Server) m_objs.peek(); + + mergeServer(to, from); + visitServerChildren(to, from); + } + + protected void visitServerChildren(Server to, Server from) { + for (Property source : from.getProperties().values()) { + Property target = to.findProperty(source.getName()); + + if (target == null) { + target = new Property(source.getName()); + to.addProperty(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + if (from.getStorage() != null) { + StorageConfig target = to.getStorage(); + + if (target == null) { + target = new StorageConfig(); + to.setStorage(target); + } + + m_objs.push(target); + from.getStorage().accept(this); + m_objs.pop(); + } + + if (from.getConsumer() != null) { + ConsumerConfig target = to.getConsumer(); + + if (target == null) { + target = new ConsumerConfig(); + to.setConsumer(target); + } + + m_objs.push(target); + from.getConsumer().accept(this); + m_objs.pop(); + } + } + + @Override + public void visitServerConfig(ServerConfig from) { + ServerConfig to = (ServerConfig) m_objs.peek(); + + mergeServerConfig(to, from); + visitServerConfigChildren(to, from); + } + + protected void visitServerConfigChildren(ServerConfig to, ServerConfig from) { + for (Server source : from.getServers().values()) { + Server target = to.findServer(source.getId()); + + if (target == null) { + target = new Server(source.getId()); + to.addServer(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } + + @Override + public void visitStorage(StorageConfig from) { + StorageConfig to = (StorageConfig) m_objs.peek(); + + mergeStorage(to, from); + visitStorageChildren(to, from); + } + + protected void visitStorageChildren(StorageConfig to, StorageConfig from) { + for (HdfsConfig source : from.getHdfses().values()) { + HdfsConfig target = to.findHdfs(source.getId()); + + if (target == null) { + target = new HdfsConfig(source.getId()); + to.addHdfs(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (HarfsConfig source : from.getHarfses().values()) { + HarfsConfig target = to.findHarfs(source.getId()); + + if (target == null) { + target = new HarfsConfig(source.getId()); + to.addHarfs(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Property source : from.getProperties().values()) { + Property target = to.findProperty(source.getName()); + + if (target == null) { + target = new Property(source.getName()); + to.addProperty(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..cd3a5bbf9a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxMaker.java @@ -0,0 +1,225 @@ +package com.dianping.cat.configuration.server.transform; + +import static com.dianping.cat.configuration.server.Constants.ATTR_BASE_DIR; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_SERVICE_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_SQL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_URL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_HAR_MODE; +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_BASE_DIR; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_LOGIVEW_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_REPORT_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_MAX_HDFS_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_MAX_SIZE; +import static com.dianping.cat.configuration.server.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.server.Constants.ATTR_SERVER_URI; +import static com.dianping.cat.configuration.server.Constants.ATTR_SERVICE_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_SQL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_UPLOAD_THREAD; +import static com.dianping.cat.configuration.server.Constants.ATTR_URL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_VALUE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public ConsumerConfig buildConsumer(Attributes attributes) { + ConsumerConfig consumer = new ConsumerConfig(); + + return consumer; + } + + @Override + public Domain buildDomain(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + String urlThreshold = attributes.getValue(ATTR_URL_THRESHOLD); + String sqlThreshold = attributes.getValue(ATTR_SQL_THRESHOLD); + String serviceThreshold = attributes.getValue(ATTR_SERVICE_THRESHOLD); + Domain domain = new Domain(name); + + if (urlThreshold != null) { + domain.setUrlThreshold(convert(Integer.class, urlThreshold, null)); + } + + if (sqlThreshold != null) { + domain.setSqlThreshold(convert(Integer.class, sqlThreshold, null)); + } + + if (serviceThreshold != null) { + domain.setServiceThreshold(convert(Integer.class, serviceThreshold, null)); + } + + return domain; + } + + @Override + public HarfsConfig buildHarfs(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String maxSize = attributes.getValue(ATTR_MAX_SIZE); + String serverUri = attributes.getValue(ATTR_SERVER_URI); + String baseDir = attributes.getValue(ATTR_BASE_DIR); + HarfsConfig harfs = new HarfsConfig(id); + + if (maxSize != null) { + harfs.setMaxSize(maxSize); + } + + if (serverUri != null) { + harfs.setServerUri(serverUri); + } + + if (baseDir != null) { + harfs.setBaseDir(baseDir); + } + + return harfs; + } + + @Override + public HdfsConfig buildHdfs(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String maxSize = attributes.getValue(ATTR_MAX_SIZE); + String serverUri = attributes.getValue(ATTR_SERVER_URI); + String baseDir = attributes.getValue(ATTR_BASE_DIR); + HdfsConfig hdfs = new HdfsConfig(id); + + if (maxSize != null) { + hdfs.setMaxSize(maxSize); + } + + if (serverUri != null) { + hdfs.setServerUri(serverUri); + } + + if (baseDir != null) { + hdfs.setBaseDir(baseDir); + } + + return hdfs; + } + + @Override + public LongConfig buildLongConfig(Attributes attributes) { + String defaultUrlThreshold = attributes.getValue(ATTR_DEFAULT_URL_THRESHOLD); + String defaultSqlThreshold = attributes.getValue(ATTR_DEFAULT_SQL_THRESHOLD); + String defaultServiceThreshold = attributes.getValue(ATTR_DEFAULT_SERVICE_THRESHOLD); + LongConfig longConfig = new LongConfig(); + + if (defaultUrlThreshold != null) { + longConfig.setDefaultUrlThreshold(convert(Integer.class, defaultUrlThreshold, 0)); + } + + if (defaultSqlThreshold != null) { + longConfig.setDefaultSqlThreshold(convert(Integer.class, defaultSqlThreshold, 0)); + } + + if (defaultServiceThreshold != null) { + longConfig.setDefaultServiceThreshold(convert(Integer.class, defaultServiceThreshold, 0)); + } + + return longConfig; + } + + @Override + public Property buildProperty(Attributes attributes) { + String name = attributes.getValue(ATTR_NAME); + String value = attributes.getValue(ATTR_VALUE); + Property property = new Property(name); + + if (value != null) { + property.setValue(value); + } + + return property; + } + + @Override + public Server buildServer(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Server server = new Server(id); + + return server; + } + + @Override + public ServerConfig buildServerConfig(Attributes attributes) { + ServerConfig serverConfig = new ServerConfig(); + + return serverConfig; + } + + @Override + public StorageConfig buildStorage(Attributes attributes) { + String localBaseDir = attributes.getValue(ATTR_LOCAL_BASE_DIR); + String maxHdfsStorageTime = attributes.getValue(ATTR_MAX_HDFS_STORAGE_TIME); + String localReportStorageTime = attributes.getValue(ATTR_LOCAL_REPORT_STORAGE_TIME); + String localLogivewStorageTime = attributes.getValue(ATTR_LOCAL_LOGIVEW_STORAGE_TIME); + String harMode = attributes.getValue(ATTR_HAR_MODE); + String uploadThread = attributes.getValue(ATTR_UPLOAD_THREAD); + StorageConfig storage = new StorageConfig(); + + if (localBaseDir != null) { + storage.setLocalBaseDir(localBaseDir); + } + + if (maxHdfsStorageTime != null) { + storage.setMaxHdfsStorageTime(convert(Integer.class, maxHdfsStorageTime, 0)); + } + + if (localReportStorageTime != null) { + storage.setLocalReportStorageTime(convert(Integer.class, localReportStorageTime, 0)); + } + + if (localLogivewStorageTime != null) { + storage.setLocalLogivewStorageTime(convert(Integer.class, localLogivewStorageTime, 0)); + } + + if (harMode != null) { + storage.setHarMode(convert(Boolean.class, harMode, false)); + } + + if (uploadThread != null) { + storage.setUploadThread(convert(Integer.class, uploadThread, 0)); + } + + return storage; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..c518764371 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultSaxParser.java @@ -0,0 +1,389 @@ +package com.dianping.cat.configuration.server.transform; + +import static com.dianping.cat.configuration.server.Constants.ENTITY_CONSUMER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HARFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HDFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_LONG_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTY; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_STORAGE; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTIES; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.server.IEntity; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static ServerConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(ServerConfig.class, new InputSource(removeBOM(in))); + } + + public static ServerConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(ServerConfig.class, new InputSource(removeBOM(reader))); + } + + public static ServerConfig parse(String xml) throws SAXException, IOException { + return parseEntity(ServerConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForConsumer(ConsumerConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_LONG_CONFIG.equals(qName)) { + LongConfig longConfig = m_maker.buildLongConfig(attributes); + + m_linker.onLongConfig(parentObj, longConfig); + m_objs.push(longConfig); + } else { + throw new SAXException(String.format("Element(%s) is not expected under consumer!", qName)); + } + + m_tags.push(qName); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForHarfs(HarfsConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForHdfs(HdfsConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForLongConfig(LongConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under long-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForProperty(Property parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForServer(Server parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PROPERTIES.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_PROPERTY.equals(qName)) { + Property property = m_maker.buildProperty(attributes); + + m_linker.onProperty(parentObj, property); + m_objs.push(property); + } else if (ENTITY_STORAGE.equals(qName)) { + StorageConfig storage = m_maker.buildStorage(attributes); + + m_linker.onStorage(parentObj, storage); + m_objs.push(storage); + } else if (ENTITY_CONSUMER.equals(qName)) { + ConsumerConfig consumer = m_maker.buildConsumer(attributes); + + m_linker.onConsumer(parentObj, consumer); + m_objs.push(consumer); + } else { + throw new SAXException(String.format("Element(%s) is not expected under server!", qName)); + } + + m_tags.push(qName); + } + + private void parseForServerConfig(ServerConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_SERVER.equals(qName)) { + Server server = m_maker.buildServer(attributes); + + m_linker.onServer(parentObj, server); + m_objs.push(server); + } else { + throw new SAXException(String.format("Element(%s) is not expected under server-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseForStorage(StorageConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PROPERTIES.equals(qName)) { + m_objs.push(parentObj); + } else if (ENTITY_HDFS.equals(qName)) { + HdfsConfig hdfs = m_maker.buildHdfs(attributes); + + m_linker.onHdfs(parentObj, hdfs); + m_objs.push(hdfs); + } else if (ENTITY_HARFS.equals(qName)) { + HarfsConfig harfs = m_maker.buildHarfs(attributes); + + m_linker.onHarfs(parentObj, harfs); + m_objs.push(harfs); + } else if (ENTITY_PROPERTY.equals(qName)) { + Property property = m_maker.buildProperty(attributes); + + m_linker.onProperty(parentObj, property); + m_objs.push(property); + } else { + throw new SAXException(String.format("Element(%s) is not expected under storage!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_SERVER_CONFIG.equals(qName)) { + ServerConfig serverConfig = m_maker.buildServerConfig(attributes); + + m_entity = serverConfig; + m_objs.push(serverConfig); + m_tags.push(qName); + } else if (ENTITY_SERVER.equals(qName)) { + Server server = m_maker.buildServer(attributes); + + m_entity = server; + m_objs.push(server); + m_tags.push(qName); + } else if (ENTITY_PROPERTY.equals(qName)) { + Property property = m_maker.buildProperty(attributes); + + m_entity = property; + m_objs.push(property); + m_tags.push(qName); + } else if (ENTITY_STORAGE.equals(qName)) { + StorageConfig storage = m_maker.buildStorage(attributes); + + m_entity = storage; + m_objs.push(storage); + m_tags.push(qName); + } else if (ENTITY_HDFS.equals(qName)) { + HdfsConfig hdfs = m_maker.buildHdfs(attributes); + + m_entity = hdfs; + m_objs.push(hdfs); + m_tags.push(qName); + } else if (ENTITY_HARFS.equals(qName)) { + HarfsConfig harfs = m_maker.buildHarfs(attributes); + + m_entity = harfs; + m_objs.push(harfs); + m_tags.push(qName); + } else if (ENTITY_CONSUMER.equals(qName)) { + ConsumerConfig consumer = m_maker.buildConsumer(attributes); + + m_entity = consumer; + m_objs.push(consumer); + m_tags.push(qName); + } else if (ENTITY_LONG_CONFIG.equals(qName)) { + LongConfig longConfig = m_maker.buildLongConfig(attributes); + + m_entity = longConfig; + m_objs.push(longConfig); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof ServerConfig) { + parseForServerConfig((ServerConfig) parent, tag, qName, attributes); + } else if (parent instanceof Server) { + parseForServer((Server) parent, tag, qName, attributes); + } else if (parent instanceof Property) { + parseForProperty((Property) parent, tag, qName, attributes); + } else if (parent instanceof StorageConfig) { + parseForStorage((StorageConfig) parent, tag, qName, attributes); + } else if (parent instanceof HdfsConfig) { + parseForHdfs((HdfsConfig) parent, tag, qName, attributes); + } else if (parent instanceof HarfsConfig) { + parseForHarfs((HarfsConfig) parent, tag, qName, attributes); + } else if (parent instanceof ConsumerConfig) { + parseForConsumer((ConsumerConfig) parent, tag, qName, attributes); + } else if (parent instanceof LongConfig) { + parseForLongConfig((LongConfig) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultValidator.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultValidator.java new file mode 100644 index 0000000000..083e4ff0a4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultValidator.java @@ -0,0 +1,205 @@ +package com.dianping.cat.configuration.server.transform; + +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.server.Constants.ENTITY_CONSUMER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HARFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HDFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_LONG_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTIES; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTY; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_STORAGE; + +import java.util.Stack; + +import com.dianping.cat.configuration.server.IVisitor; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultValidator implements IVisitor { + + private Path m_path = new Path(); + + protected void assertRequired(String name, Object value) { + if (value == null) { + throw new RuntimeException(String.format("%s at path(%s) is required!", name, m_path)); + } + } + + @Override + public void visitConsumer(ConsumerConfig consumer) { + m_path.down(ENTITY_CONSUMER); + + visitConsumerChildren(consumer); + + m_path.up(ENTITY_CONSUMER); + } + + protected void visitConsumerChildren(ConsumerConfig consumer) { + if (consumer.getLongConfig() != null) { + visitLongConfig(consumer.getLongConfig()); + } + } + + @Override + public void visitDomain(Domain domain) { + m_path.down(ENTITY_DOMAIN); + + assertRequired(ATTR_NAME, domain.getName()); + + m_path.up(ENTITY_DOMAIN); + } + + @Override + public void visitHarfs(HarfsConfig harfs) { + m_path.down(ENTITY_HARFS); + + assertRequired(ATTR_ID, harfs.getId()); + + m_path.up(ENTITY_HARFS); + } + + @Override + public void visitHdfs(HdfsConfig hdfs) { + m_path.down(ENTITY_HDFS); + + assertRequired(ATTR_ID, hdfs.getId()); + + m_path.up(ENTITY_HDFS); + } + + @Override + public void visitLongConfig(LongConfig longConfig) { + m_path.down(ENTITY_LONG_CONFIG); + + visitLongConfigChildren(longConfig); + + m_path.up(ENTITY_LONG_CONFIG); + } + + protected void visitLongConfigChildren(LongConfig longConfig) { + for (Domain domain : longConfig.getDomains().values()) { + visitDomain(domain); + } + } + + @Override + public void visitProperty(Property property) { + m_path.down(ENTITY_PROPERTY); + + assertRequired(ATTR_NAME, property.getName()); + + m_path.up(ENTITY_PROPERTY); + } + + @Override + public void visitServer(Server server) { + m_path.down(ENTITY_SERVER); + + assertRequired(ATTR_ID, server.getId()); + + visitServerChildren(server); + + m_path.up(ENTITY_SERVER); + } + + protected void visitServerChildren(Server server) { + m_path.down(ENTITY_PROPERTIES); + + for (Property property : server.getProperties().values()) { + visitProperty(property); + } + + m_path.up(ENTITY_PROPERTIES); + + if (server.getStorage() != null) { + visitStorage(server.getStorage()); + } + + if (server.getConsumer() != null) { + visitConsumer(server.getConsumer()); + } + } + + @Override + public void visitServerConfig(ServerConfig serverConfig) { + m_path.down(ENTITY_SERVER_CONFIG); + + visitServerConfigChildren(serverConfig); + + m_path.up(ENTITY_SERVER_CONFIG); + } + + protected void visitServerConfigChildren(ServerConfig serverConfig) { + for (Server server : serverConfig.getServers().values()) { + visitServer(server); + } + } + + @Override + public void visitStorage(StorageConfig storage) { + m_path.down(ENTITY_STORAGE); + + visitStorageChildren(storage); + + m_path.up(ENTITY_STORAGE); + } + + protected void visitStorageChildren(StorageConfig storage) { + for (HdfsConfig hdfs : storage.getHdfses().values()) { + visitHdfs(hdfs); + } + + for (HarfsConfig harfs : storage.getHarfses().values()) { + visitHarfs(harfs); + } + + m_path.down(ENTITY_PROPERTIES); + + for (Property property : storage.getProperties().values()) { + visitProperty(property); + } + + m_path.up(ENTITY_PROPERTIES); + } + + static class Path { + private Stack m_sections = new Stack(); + + public Path down(String nextSection) { + m_sections.push(nextSection); + + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (String section : m_sections) { + sb.append('/').append(section); + } + + return sb.toString(); + } + + public Path up(String currentSection) { + if (m_sections.isEmpty() || !m_sections.peek().equals(currentSection)) { + throw new RuntimeException("INTERNAL ERROR: stack mismatched!"); + } + + m_sections.pop(); + return this; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..1d28c505fa --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/DefaultXmlBuilder.java @@ -0,0 +1,337 @@ +package com.dianping.cat.configuration.server.transform; + +import static com.dianping.cat.configuration.server.Constants.ATTR_BASE_DIR; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_SERVICE_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_SQL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_DEFAULT_URL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_HAR_MODE; +import static com.dianping.cat.configuration.server.Constants.ATTR_ID; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_BASE_DIR; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_LOGIVEW_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_LOCAL_REPORT_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_MAX_HDFS_STORAGE_TIME; +import static com.dianping.cat.configuration.server.Constants.ATTR_MAX_SIZE; +import static com.dianping.cat.configuration.server.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.server.Constants.ATTR_SERVER_URI; +import static com.dianping.cat.configuration.server.Constants.ATTR_SERVICE_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_SQL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_UPLOAD_THREAD; +import static com.dianping.cat.configuration.server.Constants.ATTR_URL_THRESHOLD; +import static com.dianping.cat.configuration.server.Constants.ATTR_VALUE; +import static com.dianping.cat.configuration.server.Constants.ENTITY_CONSUMER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HARFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_HDFS; +import static com.dianping.cat.configuration.server.Constants.ENTITY_LONG_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTIES; +import static com.dianping.cat.configuration.server.Constants.ENTITY_PROPERTY; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER; +import static com.dianping.cat.configuration.server.Constants.ENTITY_SERVER_CONFIG; +import static com.dianping.cat.configuration.server.Constants.ENTITY_STORAGE; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.server.IEntity; +import com.dianping.cat.configuration.server.IVisitor; +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitConsumer(ConsumerConfig consumer) { + startTag(ENTITY_CONSUMER, null); + + if (consumer.getLongConfig() != null) { + consumer.getLongConfig().accept(m_visitor); + } + + endTag(ENTITY_CONSUMER); + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, true, null, ATTR_NAME, domain.getName(), ATTR_URL_THRESHOLD, domain.getUrlThreshold(), ATTR_SQL_THRESHOLD, domain.getSqlThreshold(), ATTR_SERVICE_THRESHOLD, domain.getServiceThreshold()); + } + + @Override + public void visitHarfs(HarfsConfig harfs) { + startTag(ENTITY_HARFS, true, null, ATTR_ID, harfs.getId(), ATTR_MAX_SIZE, harfs.getMaxSize(), ATTR_SERVER_URI, harfs.getServerUri(), ATTR_BASE_DIR, harfs.getBaseDir()); + } + + @Override + public void visitHdfs(HdfsConfig hdfs) { + startTag(ENTITY_HDFS, true, null, ATTR_ID, hdfs.getId(), ATTR_MAX_SIZE, hdfs.getMaxSize(), ATTR_SERVER_URI, hdfs.getServerUri(), ATTR_BASE_DIR, hdfs.getBaseDir()); + } + + @Override + public void visitLongConfig(LongConfig longConfig) { + startTag(ENTITY_LONG_CONFIG, null, ATTR_DEFAULT_URL_THRESHOLD, longConfig.getDefaultUrlThreshold(), ATTR_DEFAULT_SQL_THRESHOLD, longConfig.getDefaultSqlThreshold(), ATTR_DEFAULT_SERVICE_THRESHOLD, longConfig.getDefaultServiceThreshold()); + + if (!longConfig.getDomains().isEmpty()) { + for (Domain domain : longConfig.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_LONG_CONFIG); + } + + @Override + public void visitProperty(Property property) { + startTag(ENTITY_PROPERTY, true, null, ATTR_NAME, property.getName(), ATTR_VALUE, property.getValue()); + } + + @Override + public void visitServer(Server server) { + startTag(ENTITY_SERVER, null, ATTR_ID, server.getId()); + + if (!server.getProperties().isEmpty()) { + startTag(ENTITY_PROPERTIES); + + for (Property property : server.getProperties().values()) { + property.accept(m_visitor); + } + + endTag(ENTITY_PROPERTIES); + } + + if (server.getStorage() != null) { + server.getStorage().accept(m_visitor); + } + + if (server.getConsumer() != null) { + server.getConsumer().accept(m_visitor); + } + + endTag(ENTITY_SERVER); + } + + @Override + public void visitServerConfig(ServerConfig serverConfig) { + startTag(ENTITY_SERVER_CONFIG, null); + + if (!serverConfig.getServers().isEmpty()) { + for (Server server : serverConfig.getServers().values()) { + server.accept(m_visitor); + } + } + + endTag(ENTITY_SERVER_CONFIG); + } + + @Override + public void visitStorage(StorageConfig storage) { + startTag(ENTITY_STORAGE, null, ATTR_LOCAL_BASE_DIR, storage.getLocalBaseDir(), ATTR_MAX_HDFS_STORAGE_TIME, storage.getMaxHdfsStorageTime(), ATTR_LOCAL_REPORT_STORAGE_TIME, storage.getLocalReportStorageTime(), ATTR_LOCAL_LOGIVEW_STORAGE_TIME, storage.getLocalLogivewStorageTime(), ATTR_HAR_MODE, storage.isHarMode(), ATTR_UPLOAD_THREAD, storage.getUploadThread()); + + if (!storage.getHdfses().isEmpty()) { + for (HdfsConfig hdfs : storage.getHdfses().values()) { + hdfs.accept(m_visitor); + } + } + + if (!storage.getHarfses().isEmpty()) { + for (HarfsConfig harfs : storage.getHarfses().values()) { + harfs.accept(m_visitor); + } + } + + if (!storage.getProperties().isEmpty()) { + startTag(ENTITY_PROPERTIES); + + for (Property property : storage.getProperties().values()) { + property.accept(m_visitor); + } + + endTag(ENTITY_PROPERTIES); + } + + endTag(ENTITY_STORAGE); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/ILinker.java new file mode 100644 index 0000000000..e133f5a09a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/ILinker.java @@ -0,0 +1,32 @@ +package com.dianping.cat.configuration.server.transform; + +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public interface ILinker { + + public boolean onConsumer(Server parent, ConsumerConfig consumer); + + public boolean onDomain(LongConfig parent, Domain domain); + + public boolean onHarfs(StorageConfig parent, HarfsConfig harfs); + + public boolean onHdfs(StorageConfig parent, HdfsConfig hdfs); + + public boolean onLongConfig(ConsumerConfig parent, LongConfig longConfig); + + public boolean onProperty(Server parent, Property property); + + public boolean onProperty(StorageConfig parent, Property property); + + public boolean onServer(ServerConfig parent, Server server); + + public boolean onStorage(Server parent, StorageConfig storage); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IMaker.java new file mode 100644 index 0000000000..053c85741e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IMaker.java @@ -0,0 +1,32 @@ +package com.dianping.cat.configuration.server.transform; + +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public interface IMaker { + + public ConsumerConfig buildConsumer(T node); + + public Domain buildDomain(T node); + + public HarfsConfig buildHarfs(T node); + + public HdfsConfig buildHdfs(T node); + + public LongConfig buildLongConfig(T node); + + public Property buildProperty(T node); + + public Server buildServer(T node); + + public ServerConfig buildServerConfig(T node); + + public StorageConfig buildStorage(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IParser.java new file mode 100644 index 0000000000..9fbb1ae440 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/server/transform/IParser.java @@ -0,0 +1,31 @@ +package com.dianping.cat.configuration.server.transform; + +import com.dianping.cat.configuration.server.entity.ConsumerConfig; +import com.dianping.cat.configuration.server.entity.Domain; +import com.dianping.cat.configuration.server.entity.HarfsConfig; +import com.dianping.cat.configuration.server.entity.HdfsConfig; +import com.dianping.cat.configuration.server.entity.LongConfig; +import com.dianping.cat.configuration.server.entity.Property; +import com.dianping.cat.configuration.server.entity.Server; +import com.dianping.cat.configuration.server.entity.ServerConfig; +import com.dianping.cat.configuration.server.entity.StorageConfig; + +public interface IParser { + public ServerConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForConsumerConfig(IMaker maker, ILinker linker, ConsumerConfig parent, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); + + public void parseForHarfsConfig(IMaker maker, ILinker linker, HarfsConfig parent, T node); + + public void parseForHdfsConfig(IMaker maker, ILinker linker, HdfsConfig parent, T node); + + public void parseForLongConfig(IMaker maker, ILinker linker, LongConfig parent, T node); + + public void parseForProperty(IMaker maker, ILinker linker, Property parent, T node); + + public void parseForServer(IMaker maker, ILinker linker, Server parent, T node); + + public void parseForStorageConfig(IMaker maker, ILinker linker, StorageConfig parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/BaseEntity.java new file mode 100644 index 0000000000..23ccc32d74 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.configuration.tp; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.configuration.tp.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/Constants.java new file mode 100644 index 0000000000..8dee6c3930 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/Constants.java @@ -0,0 +1,16 @@ +package com.dianping.cat.configuration.tp; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ELEMENT_TRANSACTION_TYPE = "transaction-type"; + + public static final String ELEMENT_TRANSACTION_TYPES = "transaction-types"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_TP_VALUE_STATISTIC_CONFIG = "tp-value-statistic-config"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/IEntity.java new file mode 100644 index 0000000000..46d8a55284 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.tp; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/IVisitor.java new file mode 100644 index 0000000000..84511844b1 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/IVisitor.java @@ -0,0 +1,11 @@ +package com.dianping.cat.configuration.tp; + +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public interface IVisitor { + + public void visitDomain(Domain domain); + + public void visitTpValueStatisticConfig(TpValueStatisticConfig tpValueStatisticConfig); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/Domain.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/Domain.java new file mode 100644 index 0000000000..1a365a7eef --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/Domain.java @@ -0,0 +1,77 @@ +package com.dianping.cat.configuration.tp.entity; + +import static com.dianping.cat.configuration.tp.Constants.ATTR_ID; +import static com.dianping.cat.configuration.tp.Constants.ENTITY_DOMAIN; + +import java.util.LinkedHashSet; +import java.util.Set; + +import com.dianping.cat.configuration.tp.BaseEntity; +import com.dianping.cat.configuration.tp.IVisitor; + +public class Domain extends BaseEntity { + private String m_id; + + private Set m_transactionTypes = new LinkedHashSet(); + + public Domain() { + } + + public Domain(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + public Domain addTransactionType(String transactionType) { + m_transactionTypes.add(transactionType); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public Set getTransactionTypes() { + return m_transactionTypes; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_ID, m_id, other.getId()); + + } + + public Domain setId(String id) { + m_id = id; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/TpValueStatisticConfig.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/TpValueStatisticConfig.java new file mode 100644 index 0000000000..7a99b08944 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/entity/TpValueStatisticConfig.java @@ -0,0 +1,83 @@ +package com.dianping.cat.configuration.tp.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.tp.BaseEntity; +import com.dianping.cat.configuration.tp.IVisitor; + +public class TpValueStatisticConfig extends BaseEntity { + private Map m_domains = new LinkedHashMap(); + + public TpValueStatisticConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitTpValueStatisticConfig(this); + } + + public TpValueStatisticConfig addDomain(Domain domain) { + m_domains.put(domain.getId(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof TpValueStatisticConfig) { + TpValueStatisticConfig _o = (TpValueStatisticConfig) obj; + + if (!equals(getDomains(), _o.getDomains())) { + return false; + } + + + return true; + } + + return false; + } + + public Domain findDomain(String id) { + return m_domains.get(id); + } + + public Domain findOrCreateDomain(String id) { + Domain domain = m_domains.get(id); + + if (domain == null) { + synchronized (m_domains) { + domain = m_domains.get(id); + + if (domain == null) { + domain = new Domain(id); + m_domains.put(id, domain); + } + } + } + + return domain; + } + + public Map getDomains() { + return m_domains; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domains == null ? 0 : m_domains.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(TpValueStatisticConfig other) { + } + + public Domain removeDomain(String id) { + return m_domains.remove(id); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultLinker.java new file mode 100644 index 0000000000..b6aeec53b2 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultLinker.java @@ -0,0 +1,38 @@ +package com.dianping.cat.configuration.tp.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDomain(final TpValueStatisticConfig parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..781f7d918a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxMaker.java @@ -0,0 +1,58 @@ +package com.dianping.cat.configuration.tp.transform; + +import static com.dianping.cat.configuration.tp.Constants.ATTR_ID; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Domain buildDomain(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + Domain domain = new Domain(id); + + return domain; + } + + @Override + public TpValueStatisticConfig buildTpValueStatisticConfig(Attributes attributes) { + TpValueStatisticConfig tpValueStatisticConfig = new TpValueStatisticConfig(); + + return tpValueStatisticConfig; + } + + @Override + public String buildTransactionType(Attributes attributes) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..fec98f2dca --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultSaxParser.java @@ -0,0 +1,242 @@ +package com.dianping.cat.configuration.tp.transform; + +import static com.dianping.cat.configuration.tp.Constants.ELEMENT_TRANSACTION_TYPE; +import static com.dianping.cat.configuration.tp.Constants.ELEMENT_TRANSACTION_TYPES; + +import static com.dianping.cat.configuration.tp.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.tp.Constants.ENTITY_TP_VALUE_STATISTIC_CONFIG; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.tp.IEntity; +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static TpValueStatisticConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(TpValueStatisticConfig.class, new InputSource(removeBOM(in))); + } + + public static TpValueStatisticConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(TpValueStatisticConfig.class, new InputSource(removeBOM(reader))); + } + + public static TpValueStatisticConfig parse(String xml) throws SAXException, IOException { + return parseEntity(TpValueStatisticConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + Object currentObj = m_objs.pop(); + String currentTag = m_tags.pop(); + + if (currentObj instanceof Domain) { + Domain domain = (Domain) currentObj; + + if (ELEMENT_TRANSACTION_TYPE.equals(currentTag)) { + domain.addTransactionType(getText()); + } + } + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ELEMENT_TRANSACTION_TYPES.equals(qName) || ELEMENT_TRANSACTION_TYPE.equals(qName)) { + m_objs.push(parentObj); + } else { + throw new SAXException(String.format("Element(%s) is not expected under domain!", qName)); + } + + m_tags.push(qName); + } + + private void parseForTpValueStatisticConfig(TpValueStatisticConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under tp-value-statistic-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_TP_VALUE_STATISTIC_CONFIG.equals(qName)) { + TpValueStatisticConfig tpValueStatisticConfig = m_maker.buildTpValueStatisticConfig(attributes); + + m_entity = tpValueStatisticConfig; + m_objs.push(tpValueStatisticConfig); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof TpValueStatisticConfig) { + parseForTpValueStatisticConfig((TpValueStatisticConfig) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..a9eb4a7373 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/DefaultXmlBuilder.java @@ -0,0 +1,264 @@ +package com.dianping.cat.configuration.tp.transform; + +import static com.dianping.cat.configuration.tp.Constants.ATTR_ID; +import static com.dianping.cat.configuration.tp.Constants.ELEMENT_TRANSACTION_TYPE; +import static com.dianping.cat.configuration.tp.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.configuration.tp.Constants.ENTITY_TP_VALUE_STATISTIC_CONFIG; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.tp.IEntity; +import com.dianping.cat.configuration.tp.IVisitor; +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + protected void tagWithText(String name, String text, Object... nameValues) { + if (text == null) { + return; + } + + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + m_sb.append(">"); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } + + protected void element(String name, String text, String defaultValue, boolean escape) { + if (text == null || text.equals(defaultValue)) { + return; + } + + indent(); + + m_sb.append('<').append(name).append(">"); + + if (escape) { + m_sb.append(escape(text, true)); + } else { + m_sb.append(""); + } + + m_sb.append("\r\n"); + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, null, ATTR_ID, domain.getId()); + + if (!domain.getTransactionTypes().isEmpty()) { + for (String transactionType : domain.getTransactionTypes()) { + tagWithText(ELEMENT_TRANSACTION_TYPE, transactionType); + } + } + + endTag(ENTITY_DOMAIN); + } + + @Override + public void visitTpValueStatisticConfig(TpValueStatisticConfig tpValueStatisticConfig) { + startTag(ENTITY_TP_VALUE_STATISTIC_CONFIG, null); + + if (!tpValueStatisticConfig.getDomains().isEmpty()) { + for (Domain domain : tpValueStatisticConfig.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_TP_VALUE_STATISTIC_CONFIG); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/ILinker.java new file mode 100644 index 0000000000..424af64ad6 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/ILinker.java @@ -0,0 +1,9 @@ +package com.dianping.cat.configuration.tp.transform; + +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public interface ILinker { + + public boolean onDomain(TpValueStatisticConfig parent, Domain domain); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IMaker.java new file mode 100644 index 0000000000..71967cd427 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IMaker.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.tp.transform; + +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public interface IMaker { + + public Domain buildDomain(T node); + + public TpValueStatisticConfig buildTpValueStatisticConfig(T node); + + public String buildTransactionType(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IParser.java new file mode 100644 index 0000000000..bba3ec8b1e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/tp/transform/IParser.java @@ -0,0 +1,10 @@ +package com.dianping.cat.configuration.tp.transform; + +import com.dianping.cat.configuration.tp.entity.Domain; +import com.dianping.cat.configuration.tp.entity.TpValueStatisticConfig; + +public interface IParser { + public TpValueStatisticConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/BaseEntity.java new file mode 100644 index 0000000000..4b9f32a002 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/BaseEntity.java @@ -0,0 +1,56 @@ +package com.dianping.cat.configuration.web.url; + +import java.util.Formattable; +import java.util.FormattableFlags; +import java.util.Formatter; + +import com.dianping.cat.configuration.web.url.transform.DefaultXmlBuilder; +import com.dianping.cat.configuration.web.url.transform.DefaultJsonBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String JSON = "%#.3s"; + + public static final String JSON_COMPACT = "%#s"; + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean useJson = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE; + boolean compact = (precision <= 0); + + if (useJson) { + DefaultJsonBuilder builder = new DefaultJsonBuilder(compact); + + formatter.format("%s", builder.build(this)); + } else { + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/Constants.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/Constants.java new file mode 100644 index 0000000000..ce00f3abe7 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/Constants.java @@ -0,0 +1,26 @@ +package com.dianping.cat.configuration.web.url; + +public class Constants { + + public static final String ATTR_DOMAIN = "domain"; + + public static final String ATTR_GROUP = "group"; + + public static final String ATTR_ID = "id"; + + public static final String ATTR_NAME = "name"; + + public static final String ATTR_PATTERN = "pattern"; + + public static final String ATTR_STATUS = "status"; + + public static final String ENTITY_CODE = "code"; + + public static final String ENTITY_CODES = "codes"; + + public static final String ENTITY_PATTERN_ITEM = "pattern-item"; + + public static final String ENTITY_PATTERN_ITEMS = "pattern-items"; + + public static final String ENTITY_URL_PATTERN = "url-pattern"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IEntity.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IEntity.java new file mode 100644 index 0000000000..b9055388e6 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.configuration.web.url; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IVisitor.java new file mode 100644 index 0000000000..e8dde77ba0 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/IVisitor.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.web.url; + +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public interface IVisitor { + + public void visitCode(Code code); + + public void visitPatternItem(PatternItem patternItem); + + public void visitUrlPattern(UrlPattern urlPattern); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/Code.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/Code.java new file mode 100644 index 0000000000..3a5b6a1a60 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/Code.java @@ -0,0 +1,92 @@ +package com.dianping.cat.configuration.web.url.entity; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_ID; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_CODE; + +import com.dianping.cat.configuration.web.url.BaseEntity; +import com.dianping.cat.configuration.web.url.IVisitor; + +public class Code extends BaseEntity { + private Integer m_id; + + private String m_name; + + private Integer m_status; + + public Code() { + } + + public Code(Integer id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitCode(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Code) { + Code _o = (Code) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public Integer getId() { + return m_id; + } + + public String getName() { + return m_name; + } + + public Integer getStatus() { + return m_status; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Code other) { + assertAttributeEquals(other, ENTITY_CODE, ATTR_ID, m_id, other.getId()); + + if (other.getName() != null) { + m_name = other.getName(); + } + + if (other.getStatus() != null) { + m_status = other.getStatus(); + } + } + + public Code setId(Integer id) { + m_id = id; + return this; + } + + public Code setName(String name) { + m_name = name; + return this; + } + + public Code setStatus(Integer status) { + m_status = status; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/PatternItem.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/PatternItem.java new file mode 100644 index 0000000000..ac01da04da --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/PatternItem.java @@ -0,0 +1,120 @@ +package com.dianping.cat.configuration.web.url.entity; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_PATTERN_ITEM; + +import com.dianping.cat.configuration.web.url.BaseEntity; +import com.dianping.cat.configuration.web.url.IVisitor; + +public class PatternItem extends BaseEntity { + private String m_group; + + private String m_name; + + private String m_pattern; + + private String m_domain; + + private int m_id; + + public PatternItem() { + } + + public PatternItem(String name) { + m_name = name; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitPatternItem(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PatternItem) { + PatternItem _o = (PatternItem) obj; + + if (!equals(getName(), _o.getName())) { + return false; + } + + return true; + } + + return false; + } + + public String getDomain() { + return m_domain; + } + + public String getGroup() { + return m_group; + } + + public int getId() { + return m_id; + } + + public String getName() { + return m_name; + } + + public String getPattern() { + return m_pattern; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_name == null ? 0 : m_name.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(PatternItem other) { + assertAttributeEquals(other, ENTITY_PATTERN_ITEM, ATTR_NAME, m_name, other.getName()); + + if (other.getGroup() != null) { + m_group = other.getGroup(); + } + + if (other.getPattern() != null) { + m_pattern = other.getPattern(); + } + + if (other.getDomain() != null) { + m_domain = other.getDomain(); + } + + m_id = other.getId(); + } + + public PatternItem setDomain(String domain) { + m_domain = domain; + return this; + } + + public PatternItem setGroup(String group) { + m_group = group; + return this; + } + + public PatternItem setId(int id) { + m_id = id; + return this; + } + + public PatternItem setName(String name) { + m_name = name; + return this; + } + + public PatternItem setPattern(String pattern) { + m_pattern = pattern; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/UrlPattern.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/UrlPattern.java new file mode 100644 index 0000000000..09384bddb0 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/entity/UrlPattern.java @@ -0,0 +1,124 @@ +package com.dianping.cat.configuration.web.url.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.configuration.web.url.BaseEntity; +import com.dianping.cat.configuration.web.url.IVisitor; + +public class UrlPattern extends BaseEntity { + private Map m_patternItems = new LinkedHashMap(); + + private Map m_codes = new LinkedHashMap(); + + public UrlPattern() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitUrlPattern(this); + } + + public UrlPattern addCode(Code code) { + m_codes.put(code.getId(), code); + return this; + } + + public UrlPattern addPatternItem(PatternItem patternItem) { + m_patternItems.put(patternItem.getName(), patternItem); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof UrlPattern) { + UrlPattern _o = (UrlPattern) obj; + + if (!equals(getPatternItems(), _o.getPatternItems())) { + return false; + } + + if (!equals(getCodes(), _o.getCodes())) { + return false; + } + + + return true; + } + + return false; + } + + public Code findCode(Integer id) { + return m_codes.get(id); + } + + public PatternItem findPatternItem(String name) { + return m_patternItems.get(name); + } + + public Code findOrCreateCode(Integer id) { + Code code = m_codes.get(id); + + if (code == null) { + synchronized (m_codes) { + code = m_codes.get(id); + + if (code == null) { + code = new Code(id); + m_codes.put(id, code); + } + } + } + + return code; + } + + public PatternItem findOrCreatePatternItem(String name) { + PatternItem patternItem = m_patternItems.get(name); + + if (patternItem == null) { + synchronized (m_patternItems) { + patternItem = m_patternItems.get(name); + + if (patternItem == null) { + patternItem = new PatternItem(name); + m_patternItems.put(name, patternItem); + } + } + } + + return patternItem; + } + + public Map getCodes() { + return m_codes; + } + + public Map getPatternItems() { + return m_patternItems; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_patternItems == null ? 0 : m_patternItems.hashCode()); + hash = hash * 31 + (m_codes == null ? 0 : m_codes.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(UrlPattern other) { + } + + public Code removeCode(Integer id) { + return m_codes.remove(id); + } + + public PatternItem removePatternItem(String name) { + return m_patternItems.remove(name); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/BaseVisitor.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/BaseVisitor.java new file mode 100644 index 0000000000..b126dbc845 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/BaseVisitor.java @@ -0,0 +1,27 @@ +package com.dianping.cat.configuration.web.url.transform; + +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public abstract class BaseVisitor implements IVisitor { + @Override + public void visitCode(Code code) { + } + + @Override + public void visitPatternItem(PatternItem patternItem) { + } + + @Override + public void visitUrlPattern(UrlPattern urlPattern) { + for (PatternItem patternItem : urlPattern.getPatternItems().values()) { + visitPatternItem(patternItem); + } + + for (Code code : urlPattern.getCodes().values()) { + visitCode(code); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonBuilder.java new file mode 100644 index 0000000000..46e2d6cf4f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonBuilder.java @@ -0,0 +1,282 @@ +package com.dianping.cat.configuration.web.url.transform; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_DOMAIN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_GROUP; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_ID; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_PATTERN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_STATUS; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_CODES; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_PATTERN_ITEMS; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + +import com.dianping.cat.configuration.web.url.IEntity; +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultJsonBuilder implements IVisitor { + + private IVisitor m_visitor; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultJsonBuilder() { + this(false); + } + + public DefaultJsonBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultJsonBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_visitor = this; + } + + protected void arrayBegin(String name) { + indent(); + m_sb.append('"').append(name).append(m_compact ? "\":[" : "\": [\r\n"); + m_level++; + } + + protected void arrayEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append("],").append(m_compact ? "" : "\r\n"); + } + + protected void attributes(Map dynamicAttributes, Object... nameValues) { + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + if (attrValue instanceof Collection) { + @SuppressWarnings("unchecked") + Collection items = (Collection) attrValue; + + if (!items.isEmpty()) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (Object item : items) { + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else if (attrValue.getClass().isArray()) { + int length = Array.getLength(attrValue); + + if (length > 0) { + indent(); + m_sb.append('"').append(attrName).append(m_compact ? "\":[" : "\": ["); + + for (int j = 0; j < length; j++) { + Object item = Array.get(attrValue, j); + m_sb.append(' '); + toString(m_sb, item); + m_sb.append(','); + } + + m_sb.setLength(m_sb.length() - 1); + m_sb.append(m_compact ? "]," : " ],\r\n"); + } + } else { + if (m_compact) { + m_sb.append('"').append(attrName).append("\":"); + toString(m_sb, attrValue); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(attrName).append("\": "); + toString(m_sb, attrValue); + m_sb.append(",\r\n"); + } + } + } + } + + if (dynamicAttributes != null) { + for (Map.Entry e : dynamicAttributes.entrySet()) { + if (m_compact) { + m_sb.append('"').append(e.getKey()).append("\":"); + toString(m_sb, e.getValue()); + m_sb.append(","); + } else { + indent(); + m_sb.append('"').append(e.getKey()).append("\": "); + toString(m_sb, e.getValue()); + m_sb.append(",\r\n"); + } + } + } + } + + public String build(IEntity entity) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + trimComma(); + + return m_sb.toString(); + } + + public String buildArray(Collection> entities) { + m_sb.append('['); + + if (entities != null) { + for (IEntity entity : entities) { + objectBegin(null); + entity.accept(this); + objectEnd(null); + } + + trimComma(); + } + + m_sb.append(']'); + + return m_sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void objectBegin(String name) { + indent(); + + if (name == null) { + m_sb.append("{").append(m_compact ? "" : "\r\n"); + } else { + m_sb.append('"').append(name).append(m_compact ? "\":{" : "\": {\r\n"); + } + + m_level++; + } + + protected void objectEnd(String name) { + m_level--; + + trimComma(); + indent(); + m_sb.append(m_compact ? "}," : "},\r\n"); + } + + protected void toString(StringBuilder sb, Object value) { + if (value == null) { + sb.append("null"); + } else if (value instanceof Boolean || value instanceof Number) { + sb.append(value); + } else { + String val = value.toString(); + int len = val.length(); + + sb.append('"'); + + for (int i = 0; i < len; i++) { + char ch = val.charAt(i); + + switch (ch) { + case '\\': + case '/': + case '"': + sb.append('\\').append(ch); + break; + case '\t': + sb.append("\\t"); + break; + case '\r': + sb.append("\\r"); + break; + case '\n': + sb.append("\\n"); + break; + default: + sb.append(ch); + break; + } + } + + sb.append('"'); + } + } + + protected void trimComma() { + int len = m_sb.length(); + + if (m_compact) { + if (len > 1 && m_sb.charAt(len - 1) == ',') { + m_sb.replace(len - 1, len, ""); + } + } else { + if (len > 3 && m_sb.charAt(len - 3) == ',') { + m_sb.replace(len - 3, len - 2, ""); + } + } + } + + @Override + public void visitCode(Code code) { + attributes(null, ATTR_ID, code.getId(), ATTR_NAME, code.getName(), ATTR_STATUS, code.getStatus()); + } + + @Override + public void visitPatternItem(PatternItem patternItem) { + attributes(null, ATTR_GROUP, patternItem.getGroup(), ATTR_NAME, patternItem.getName(), ATTR_PATTERN, patternItem.getPattern(), ATTR_DOMAIN, patternItem.getDomain(), ATTR_ID, patternItem.getId()); + } + + @Override + public void visitUrlPattern(UrlPattern urlPattern) { + + if (!urlPattern.getPatternItems().isEmpty()) { + objectBegin(ENTITY_PATTERN_ITEMS); + + for (Map.Entry e : urlPattern.getPatternItems().entrySet()) { + String key = String.valueOf(e.getKey()); + + objectBegin(key); + e.getValue().accept(m_visitor); + objectEnd(key); + } + + objectEnd(ENTITY_PATTERN_ITEMS); + } + + if (!urlPattern.getCodes().isEmpty()) { + objectBegin(ENTITY_CODES); + + for (Map.Entry e : urlPattern.getCodes().entrySet()) { + String key = String.valueOf(e.getKey()); + + objectBegin(key); + e.getValue().accept(m_visitor); + objectEnd(key); + } + + objectEnd(ENTITY_CODES); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonParser.java new file mode 100644 index 0000000000..a469584681 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultJsonParser.java @@ -0,0 +1,375 @@ +package com.dianping.cat.configuration.web.url.transform; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_DOMAIN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_GROUP; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_ID; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_PATTERN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_STATUS; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_CODES; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_PATTERN_ITEMS; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import com.dianping.cat.configuration.web.url.IEntity; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultJsonParser { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private List m_entities = new ArrayList(); + + private Class m_entityClass; + + private DefaultJsonParser(Class entityClass) { + m_entityClass = entityClass; + } + + public static > T parse(Class entityClass, InputStream in) throws IOException { + return parse(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > T parse(Class entityClass, Reader reader) throws IOException { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.onArrayBegin(); + parser.parse(new JsonReader(reader)); + parser.onArrayEnd(); + + if (parser.m_entities.isEmpty()) { + return null; + } else { + return (T) parser.m_entities.get(0); + } + } + + public static > T parse(Class entityClass, String json) throws IOException { + return parse(entityClass, new StringReader(json)); + } + + public static > List parseArray(Class entityClass, InputStream in) throws Exception { + return parseArray(entityClass, new InputStreamReader(in, "utf-8")); + } + + @SuppressWarnings("unchecked") + public static > List parseArray(Class entityClass, Reader reader) throws Exception { + DefaultJsonParser parser = new DefaultJsonParser(entityClass); + + parser.parse(new JsonReader(reader)); + return (List) (List) parser.m_entities; + } + + public static > List parseArray(Class entityClass, String json) throws Exception { + return parseArray(entityClass, new StringReader(json)); + } + + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + private Object createRootEntity() { + try { + Object entity = m_entityClass.newInstance(); + + return entity; + } catch (Exception e) { + throw new RuntimeException(String.format("Unable to create entity(%s) instance!", m_entityClass.getName()), e); + } + } + + private boolean isTopLevel() { + return m_objs.size() == 1; + } + + protected void onArrayBegin() { + if (m_objs.isEmpty()) { + m_objs.push(m_entities); + m_tags.push(""); + } } + + protected void onArrayEnd() { + m_objs.pop(); + m_tags.pop(); + + } + protected void onName(String name) { + m_tags.push(name); + } + + protected void onObjectBegin() { + if (isTopLevel()) { + m_objs.push(createRootEntity()); + m_tags.push(""); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof UrlPattern) { + if (ENTITY_PATTERN_ITEMS.equals(tag) || ENTITY_CODES.equals(tag)) { + m_objs.push(parent); + } else { + String parentTag = m_tags.size() >= 2 ? m_tags.get(m_tags.size() - 2) : null; + + if (ENTITY_PATTERN_ITEMS.equals(parentTag)) { + PatternItem patternItems = new PatternItem(); + + m_linker.onPatternItem((UrlPattern) parent, patternItems); + m_objs.push(patternItems); + } else if (ENTITY_CODES.equals(parentTag)) { + Code codes = new Code(); + + m_linker.onCode((UrlPattern) parent, codes); + m_objs.push(codes); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } + } else { + throw new RuntimeException(String.format("Unknown tag(%s) found at %s!", tag, m_tags)); + } + } + } + + protected void onObjectEnd() { + m_tags.pop(); + + Object entity = m_objs.pop(); + + if (isTopLevel()) { + m_entities.add(entity); + } + } + + protected void onValue(String value) { + Object parent = m_objs.peek(); + String tag = m_tags.pop(); + + if (parent instanceof UrlPattern) { + parseForUrlPattern((UrlPattern) parent, tag, value); + } else if (parent instanceof PatternItem) { + parseForPatternItem((PatternItem) parent, tag, value); + } else if (parent instanceof Code) { + parseForCode((Code) parent, tag, value); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) under %s!", tag, parent)); + } + } + + private void parse(JsonReader reader) throws IOException { + try { + reader.parse(this); + } catch (EOFException e) { + if (m_objs.size() > 1) { + throw new EOFException(String.format("Unexpected end while parsing json! tags: %s.", m_tags)); + } + } + + m_linker.finish(); + } + + public void parseForCode(Code code, String tag, String value) { + if (ATTR_ID.equals(tag)) { + code.setId(convert(Integer.class, value, null)); + } else if (ATTR_NAME.equals(tag)) { + code.setName(value); + } else if (ATTR_STATUS.equals(tag)) { + code.setStatus(convert(Integer.class, value, null)); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, code, m_tags)); + } + } + + public void parseForPatternItem(PatternItem patternItem, String tag, String value) { + if (ATTR_GROUP.equals(tag)) { + patternItem.setGroup(value); + } else if (ATTR_NAME.equals(tag)) { + patternItem.setName(value); + } else if (ATTR_PATTERN.equals(tag)) { + patternItem.setPattern(value); + } else if (ATTR_DOMAIN.equals(tag)) { + patternItem.setDomain(value); + } else if (ATTR_ID.equals(tag)) { + patternItem.setId(convert(Integer.class, value, 0)); + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, patternItem, m_tags)); + } + } + + public void parseForUrlPattern(UrlPattern urlPattern, String tag, String value) { + if (ENTITY_PATTERN_ITEMS.equals(tag) || ENTITY_CODES.equals(tag)) { + // do nothing here + } else { + throw new RuntimeException(String.format("Unknown tag(%s) of %s under %s!", tag, urlPattern, m_tags)); + } + } + + + static class JsonReader { + private Reader m_reader; + + private char[] m_buffer = new char[2048]; + + private int m_size; + + private int m_index; + + public JsonReader(Reader reader) { + m_reader = reader; + } + + private char next() throws IOException { + if (m_index >= m_size) { + m_size = m_reader.read(m_buffer); + m_index = 0; + + if (m_size == -1) { + throw new EOFException(); + } + } + + return m_buffer[m_index++]; + } + + public void parse(DefaultJsonParser parser) throws IOException { + StringBuilder sb = new StringBuilder(); + boolean flag = false; + + while (true) { + char ch = next(); + + switch (ch) { + case ' ': + case '\t': + case '\r': + case '\n': + break; + case '{': + parser.onObjectBegin(); + flag = false; + break; + case '}': + if (flag) { // have value + parser.onValue(sb.toString()); + sb.setLength(0); + } + + parser.onObjectEnd(); + flag = false; + break; + case '\'': + case '"': + while (true) { + char ch2 = next(); + + if (ch2 != ch) { + if (ch2 == '\\') { + char ch3 = next(); + + switch (ch3) { + case 't': + sb.append('\t'); + break; + case 'r': + sb.append('\r'); + break; + case 'n': + sb.append('\n'); + break; + default: + sb.append(ch3); + break; + } + } else { + sb.append(ch2); + } + } else { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + flag = false; + } + + sb.setLength(0); + break; + } + } + + break; + case ':': + if (sb.length() != 0) { + parser.onName(sb.toString()); + sb.setLength(0); + } + + flag = true; + break; + case ',': + if (sb.length() != 0) { + if (!flag) { + parser.onName(sb.toString()); + } else { + parser.onValue(sb.toString()); + } + + sb.setLength(0); + } + + flag = false; + break; + case '[': + parser.onArrayBegin(); + flag = false; + break; + case ']': + parser.onArrayEnd(); + flag = false; + break; + default: + sb.append(ch); + break; + } + } + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultLinker.java new file mode 100644 index 0000000000..827ab70edc --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultLinker.java @@ -0,0 +1,55 @@ +package com.dianping.cat.configuration.web.url.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onCode(final UrlPattern parent, final Code code) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addCode(code); + } + }); + } else { + parent.addCode(code); + } + + return true; + } + + @Override + public boolean onPatternItem(final UrlPattern parent, final PatternItem patternItem) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addPatternItem(patternItem); + } + }); + } else { + parent.addPatternItem(patternItem); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultMerger.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultMerger.java new file mode 100644 index 0000000000..a6448e817e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultMerger.java @@ -0,0 +1,108 @@ +package com.dianping.cat.configuration.web.url.transform; + +import java.util.Stack; + +import com.dianping.cat.configuration.web.url.IEntity; +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultMerger implements IVisitor { + + private Stack m_objs = new Stack(); + + private UrlPattern m_urlPattern; + + public DefaultMerger() { + } + + public DefaultMerger(UrlPattern urlPattern) { + m_urlPattern = urlPattern; + m_objs.push(urlPattern); + } + + public UrlPattern getUrlPattern() { + return m_urlPattern; + } + + protected Stack getObjects() { + return m_objs; + } + + public void merge(IEntity to, IEntity from) { + m_objs.push(to); + from.accept(this); + m_objs.pop(); + } + + protected void mergeCode(Code to, Code from) { + to.mergeAttributes(from); + } + + protected void mergePatternItem(PatternItem to, PatternItem from) { + to.mergeAttributes(from); + } + + protected void mergeUrlPattern(UrlPattern to, UrlPattern from) { + to.mergeAttributes(from); + } + + @Override + public void visitCode(Code from) { + Code to = (Code) m_objs.peek(); + + mergeCode(to, from); + visitCodeChildren(to, from); + } + + protected void visitCodeChildren(Code to, Code from) { + } + + @Override + public void visitPatternItem(PatternItem from) { + PatternItem to = (PatternItem) m_objs.peek(); + + mergePatternItem(to, from); + visitPatternItemChildren(to, from); + } + + protected void visitPatternItemChildren(PatternItem to, PatternItem from) { + } + + @Override + public void visitUrlPattern(UrlPattern from) { + UrlPattern to = (UrlPattern) m_objs.peek(); + + mergeUrlPattern(to, from); + visitUrlPatternChildren(to, from); + } + + protected void visitUrlPatternChildren(UrlPattern to, UrlPattern from) { + for (PatternItem source : from.getPatternItems().values()) { + PatternItem target = to.findPatternItem(source.getName()); + + if (target == null) { + target = new PatternItem(source.getName()); + to.addPatternItem(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + + for (Code source : from.getCodes().values()) { + Code target = to.findCode(source.getId()); + + if (target == null) { + target = new Code(source.getId()); + to.addCode(target); + } + + m_objs.push(target); + source.accept(this); + m_objs.pop(); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeBuilder.java new file mode 100644 index 0000000000..bef1fd0946 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeBuilder.java @@ -0,0 +1,147 @@ +package com.dianping.cat.configuration.web.url.transform; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultNativeBuilder implements IVisitor { + + private IVisitor m_visitor; + + private DataOutputStream m_out; + + public DefaultNativeBuilder(OutputStream out) { + this(out, null); + } + + public DefaultNativeBuilder(OutputStream out, IVisitor visitor) { + m_out = new DataOutputStream(out); + m_visitor = (visitor == null ? this : visitor); + } + + public static byte[] build(UrlPattern urlPattern) { + ByteArrayOutputStream out = new ByteArrayOutputStream(8192); + + build(urlPattern, out); + return out.toByteArray(); + } + + public static void build(UrlPattern urlPattern, OutputStream out) { + urlPattern.accept(new DefaultNativeBuilder(out)); + } + + @Override + public void visitCode(Code code) { + if (code.getId() != null) { + writeTag(1, 1); + writeInt(code.getId()); + } + + if (code.getName() != null) { + writeTag(2, 1); + writeString(code.getName()); + } + + if (code.getStatus() != null) { + writeTag(3, 1); + writeInt(code.getStatus()); + } + + writeTag(63, 3); + } + + @Override + public void visitPatternItem(PatternItem patternItem) { + if (patternItem.getGroup() != null) { + writeTag(1, 1); + writeString(patternItem.getGroup()); + } + + if (patternItem.getName() != null) { + writeTag(2, 1); + writeString(patternItem.getName()); + } + + if (patternItem.getPattern() != null) { + writeTag(3, 1); + writeString(patternItem.getPattern()); + } + + if (patternItem.getDomain() != null) { + writeTag(4, 1); + writeString(patternItem.getDomain()); + } + + writeTag(5, 0); + writeInt(patternItem.getId()); + + writeTag(63, 3); + } + + @Override + public void visitUrlPattern(UrlPattern urlPattern) { + writeTag(63, 0); + + if (!urlPattern.getPatternItems().isEmpty()) { + writeTag(33, 2); + writeInt(urlPattern.getPatternItems().size()); + + for (PatternItem patternItem : urlPattern.getPatternItems().values()) { + patternItem.accept(m_visitor); + } + } + + if (!urlPattern.getCodes().isEmpty()) { + writeTag(34, 2); + writeInt(urlPattern.getCodes().size()); + + for (Code code : urlPattern.getCodes().values()) { + code.accept(m_visitor); + } + } + + writeTag(63, 3); + } + + private void writeInt(int value) { + try { + writeVarint(value & 0xFFFFFFFFL); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeString(String value) { + try { + m_out.writeUTF(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void writeTag(int field, int type) { + try { + m_out.writeByte((field << 2) + type); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected void writeVarint(long value) throws IOException { + while (true) { + if ((value & ~0x7FL) == 0) { + m_out.writeByte((byte) value); + return; + } else { + m_out.writeByte(((byte) value & 0x7F) | 0x80); + value >>>= 7; + } + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeParser.java new file mode 100644 index 0000000000..4b74c47b64 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultNativeParser.java @@ -0,0 +1,184 @@ +package com.dianping.cat.configuration.web.url.transform; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultNativeParser implements IVisitor { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DataInputStream m_in; + + public DefaultNativeParser(InputStream in) { + m_in = new DataInputStream(in); + } + + public static UrlPattern parse(byte[] data) { + return parse(new ByteArrayInputStream(data)); + } + + public static UrlPattern parse(InputStream in) { + DefaultNativeParser parser = new DefaultNativeParser(in); + UrlPattern urlPattern = new UrlPattern(); + + try { + urlPattern.accept(parser); + } catch (RuntimeException e) { + if (e.getCause() !=null && e.getCause() instanceof java.io.EOFException) { + // ignore it + } else { + throw e; + } + } + + parser.m_linker.finish(); + return urlPattern; + } + + @Override + public void visitCode(Code code) { + byte tag; + + while ((tag = readTag()) != -1) { + visitCodeChildren(code, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitCodeChildren(Code code, int _field, int _type) { + switch (_field) { + case 1: + code.setId(readInt()); + break; + case 2: + code.setName(readString()); + break; + case 3: + code.setStatus(readInt()); + break; + } + } + + @Override + public void visitPatternItem(PatternItem patternItem) { + byte tag; + + while ((tag = readTag()) != -1) { + visitPatternItemChildren(patternItem, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitPatternItemChildren(PatternItem patternItem, int _field, int _type) { + switch (_field) { + case 1: + patternItem.setGroup(readString()); + break; + case 2: + patternItem.setName(readString()); + break; + case 3: + patternItem.setPattern(readString()); + break; + case 4: + patternItem.setDomain(readString()); + break; + case 5: + patternItem.setId(readInt()); + break; + } + } + + @Override + public void visitUrlPattern(UrlPattern urlPattern) { + byte tag; + + if ((tag = readTag()) != -4) { + throw new RuntimeException(String.format("Malformed payload, expected: %s, but was: %s!", -4, tag)); + } + + while ((tag = readTag()) != -1) { + visitUrlPatternChildren(urlPattern, (tag & 0xFF) >> 2, tag & 0x3); + } + } + + protected void visitUrlPatternChildren(UrlPattern urlPattern, int _field, int _type) { + switch (_field) { + case 33: + if (_type == 1) { + PatternItem patternItem = new PatternItem(); + + visitPatternItem(patternItem); + m_linker.onPatternItem(urlPattern, patternItem); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + PatternItem patternItem = new PatternItem(); + + visitPatternItem(patternItem); + m_linker.onPatternItem(urlPattern, patternItem); + } + } + break; + case 34: + if (_type == 1) { + Code code = new Code(); + + visitCode(code); + m_linker.onCode(urlPattern, code); + } else if (_type == 2) { + for (int i = readInt(); i > 0; i--) { + Code code = new Code(); + + visitCode(code); + m_linker.onCode(urlPattern, code); + } + } + break; + } + } + + private int readInt() { + try { + return (int) readVarint(32); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String readString() { + try { + return m_in.readUTF(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private byte readTag() { + try { + return m_in.readByte(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + protected long readVarint(final int length) throws IOException { + int shift = 0; + long result = 0; + + while (shift < length) { + final byte b = m_in.readByte(); + result |= (long) (b & 0x7F) << shift; + if ((b & 0x80) == 0) { + return result; + } + shift += 7; + } + + throw new RuntimeException("Malformed variable int " + length + "!"); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..a840f4b3b1 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxMaker.java @@ -0,0 +1,97 @@ +package com.dianping.cat.configuration.web.url.transform; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_DOMAIN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_GROUP; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_ID; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_PATTERN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_STATUS; + +import org.xml.sax.Attributes; + +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Code buildCode(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String name = attributes.getValue(ATTR_NAME); + String status = attributes.getValue(ATTR_STATUS); + Code code = new Code(id == null ? null : convert(Integer.class, id, null)); + + if (name != null) { + code.setName(name); + } + + if (status != null) { + code.setStatus(convert(Integer.class, status, null)); + } + + return code; + } + + @Override + public PatternItem buildPatternItem(Attributes attributes) { + String group = attributes.getValue(ATTR_GROUP); + String name = attributes.getValue(ATTR_NAME); + String pattern = attributes.getValue(ATTR_PATTERN); + String domain = attributes.getValue(ATTR_DOMAIN); + String id = attributes.getValue(ATTR_ID); + PatternItem patternItem = new PatternItem(name); + + if (group != null) { + patternItem.setGroup(group); + } + + if (pattern != null) { + patternItem.setPattern(pattern); + } + + if (domain != null) { + patternItem.setDomain(domain); + } + + if (id != null) { + patternItem.setId(convert(Integer.class, id, 0)); + } + + return patternItem; + } + + @Override + public UrlPattern buildUrlPattern(Attributes attributes) { + UrlPattern urlPattern = new UrlPattern(); + + return urlPattern; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..7e0712caff --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultSaxParser.java @@ -0,0 +1,247 @@ +package com.dianping.cat.configuration.web.url.transform; + +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_CODE; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_PATTERN_ITEM; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_URL_PATTERN; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.configuration.web.url.IEntity; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static UrlPattern parse(InputStream in) throws SAXException, IOException { + return parseEntity(UrlPattern.class, new InputSource(removeBOM(in))); + } + + public static UrlPattern parse(Reader reader) throws SAXException, IOException { + return parseEntity(UrlPattern.class, new InputSource(removeBOM(reader))); + } + + public static UrlPattern parse(String xml) throws SAXException, IOException { + return parseEntity(UrlPattern.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForCode(Code parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForPatternItem(PatternItem parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForUrlPattern(UrlPattern parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_PATTERN_ITEM.equals(qName)) { + PatternItem patternItem = m_maker.buildPatternItem(attributes); + + m_linker.onPatternItem(parentObj, patternItem); + m_objs.push(patternItem); + } else if (ENTITY_CODE.equals(qName)) { + Code code = m_maker.buildCode(attributes); + + m_linker.onCode(parentObj, code); + m_objs.push(code); + } else { + throw new SAXException(String.format("Element(%s) is not expected under url-pattern!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_URL_PATTERN.equals(qName)) { + UrlPattern urlPattern = m_maker.buildUrlPattern(attributes); + + m_entity = urlPattern; + m_objs.push(urlPattern); + m_tags.push(qName); + } else if (ENTITY_PATTERN_ITEM.equals(qName)) { + PatternItem patternItem = m_maker.buildPatternItem(attributes); + + m_entity = patternItem; + m_objs.push(patternItem); + m_tags.push(qName); + } else if (ENTITY_CODE.equals(qName)) { + Code code = m_maker.buildCode(attributes); + + m_entity = code; + m_objs.push(code); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof UrlPattern) { + parseForUrlPattern((UrlPattern) parent, tag, qName, attributes); + } else if (parent instanceof PatternItem) { + parseForPatternItem((PatternItem) parent, tag, qName, attributes); + } else if (parent instanceof Code) { + parseForCode((Code) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..7dff85b086 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/DefaultXmlBuilder.java @@ -0,0 +1,230 @@ +package com.dianping.cat.configuration.web.url.transform; + +import static com.dianping.cat.configuration.web.url.Constants.ATTR_DOMAIN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_GROUP; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_ID; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_NAME; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_PATTERN; +import static com.dianping.cat.configuration.web.url.Constants.ATTR_STATUS; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_CODE; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_PATTERN_ITEM; +import static com.dianping.cat.configuration.web.url.Constants.ENTITY_URL_PATTERN; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.configuration.web.url.IEntity; +import com.dianping.cat.configuration.web.url.IVisitor; +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitCode(Code code) { + startTag(ENTITY_CODE, true, null, ATTR_ID, code.getId(), ATTR_NAME, code.getName(), ATTR_STATUS, code.getStatus()); + } + + @Override + public void visitPatternItem(PatternItem patternItem) { + startTag(ENTITY_PATTERN_ITEM, true, null, ATTR_GROUP, patternItem.getGroup(), ATTR_NAME, patternItem.getName(), ATTR_PATTERN, patternItem.getPattern(), ATTR_DOMAIN, patternItem.getDomain(), ATTR_ID, patternItem.getId()); + } + + @Override + public void visitUrlPattern(UrlPattern urlPattern) { + startTag(ENTITY_URL_PATTERN, null); + + if (!urlPattern.getPatternItems().isEmpty()) { + for (PatternItem patternItem : urlPattern.getPatternItems().values()) { + patternItem.accept(m_visitor); + } + } + + if (!urlPattern.getCodes().isEmpty()) { + for (Code code : urlPattern.getCodes().values()) { + code.accept(m_visitor); + } + } + + endTag(ENTITY_URL_PATTERN); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/ILinker.java new file mode 100644 index 0000000000..269a0634bd --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/ILinker.java @@ -0,0 +1,12 @@ +package com.dianping.cat.configuration.web.url.transform; + +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public interface ILinker { + + public boolean onCode(UrlPattern parent, Code code); + + public boolean onPatternItem(UrlPattern parent, PatternItem patternItem); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IMaker.java new file mode 100644 index 0000000000..9f1572d139 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IMaker.java @@ -0,0 +1,14 @@ +package com.dianping.cat.configuration.web.url.transform; + +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public interface IMaker { + + public Code buildCode(T node); + + public PatternItem buildPatternItem(T node); + + public UrlPattern buildUrlPattern(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IParser.java new file mode 100644 index 0000000000..808d237c7e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/configuration/web/url/transform/IParser.java @@ -0,0 +1,13 @@ +package com.dianping.cat.configuration.web.url.transform; + +import com.dianping.cat.configuration.web.url.entity.Code; +import com.dianping.cat.configuration.web.url.entity.PatternItem; +import com.dianping.cat.configuration.web.url.entity.UrlPattern; + +public interface IParser { + public UrlPattern parse(IMaker maker, ILinker linker, T node); + + public void parseForCode(IMaker maker, ILinker linker, Code parent, T node); + + public void parseForPatternItem(IMaker maker, ILinker linker, PatternItem parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/config/BusinessConfig.java b/cat-core/src/main/java/com/dianping/cat/core/config/BusinessConfig.java new file mode 100644 index 0000000000..2c83063f06 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/config/BusinessConfig.java @@ -0,0 +1,122 @@ +package com.dianping.cat.core.config; + + +public class BusinessConfig { + private long m_id; + + private String m_name; + + private String m_domain; + + private String m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public String getContent() { + return m_content; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public String getName() { + return m_name; + } + + public java.util.Date getUpdatetime() { + return m_updateTime; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public BusinessConfig setContent(String content) { + m_content = content; + return this; + } + + public BusinessConfig setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public BusinessConfig setDomain(String domain) { + m_domain = domain; + return this; + } + + public BusinessConfig setId(int id) { + m_id = id; + m_keyId = id; + return this; + } + + public BusinessConfig setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public BusinessConfig setKeyId(int keyId) { + m_keyId = keyId; + return this; + } + + public BusinessConfig setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public BusinessConfig setName(String name) { + m_name = name; + return this; + } + + public BusinessConfig setUpdatetime(java.util.Date updatetime) { + m_updateTime = updatetime; + return this; + } + + public BusinessConfig setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("BusinessConfig["); + sb.append("content: ").append(m_content); + sb.append(", create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", name: ").append(m_name); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/config/Config.java b/cat-core/src/main/java/com/dianping/cat/core/config/Config.java new file mode 100644 index 0000000000..4074136ccf --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/config/Config.java @@ -0,0 +1,108 @@ +package com.dianping.cat.core.config; + + +public class Config { + private long m_id; + + private String m_name; + + private String m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public String getContent() { + return m_content; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public java.util.Date getModifyDate() { + return m_updateTime; + } + + public String getName() { + return m_name; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public Config setContent(String content) { + m_content = content; + return this; + } + + public Config setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public Config setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public Config setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public Config setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public Config setModifyDate(java.util.Date modifyDate) { + m_updateTime = modifyDate; + return this; + } + + public Config setName(String name) { + m_name = name; + return this; + } + + public Config setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("Config["); + sb.append("content: ").append(m_content); + sb.append(", create-time: ").append(m_createTime); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", update-time: ").append(m_updateTime); + sb.append(", name: ").append(m_name); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReport.java b/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReport.java new file mode 100644 index 0000000000..cc994b7e0e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReport.java @@ -0,0 +1,171 @@ +package com.dianping.cat.core.dal; + + +public class DailyReport { + private long m_id; + + private String m_name; + + private String m_ip; + + private String m_domain; + + private java.util.Date m_period; + + private int m_type; + + private java.util.Date m_createTime; + + private long m_keyId; + + private int m_count; + + private java.util.Date m_startDate; + + private java.util.Date m_endDate; + + private int m_limits; + public void afterLoad() { + m_keyId = m_id; + } + + public int getCount() { + return m_count; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getEndDate() { + return m_endDate; + } + + public long getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public long getKeyId() { + return m_keyId; + } + + public int getLimits() { + return m_limits; + } + + public String getName() { + return m_name; + } + + public java.util.Date getPeriod() { + return m_period; + } + + public java.util.Date getStartDate() { + return m_startDate; + } + + public int getType() { + return m_type; + } + + public DailyReport setCount(int count) { + m_count = count; + return this; + } + + public DailyReport setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public DailyReport setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public DailyReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public DailyReport setEndDate(java.util.Date endDate) { + m_endDate = endDate; + return this; + } + + public DailyReport setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public DailyReport setIp(String ip) { + m_ip = ip; + return this; + } + + public DailyReport setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public DailyReport setLimits(int limits) { + m_limits = limits; + return this; + } + + public DailyReport setName(String name) { + m_name = name; + return this; + } + + public DailyReport setPeriod(java.util.Date period) { + m_period = period; + return this; + } + + public DailyReport setStartDate(java.util.Date startDate) { + m_startDate = startDate; + return this; + } + + public DailyReport setType(int type) { + m_type = type; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("DailyReport["); + sb.append("count: ").append(m_count); + sb.append(", create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", end-date: ").append(m_endDate); + sb.append(", id: ").append(m_id); + sb.append(", ip: ").append(m_ip); + sb.append(", key-id: ").append(m_keyId); + sb.append(", limits: ").append(m_limits); + sb.append(", name: ").append(m_name); + sb.append(", period: ").append(m_period); + sb.append(", start-date: ").append(m_startDate); + sb.append(", type: ").append(m_type); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReportContent.java b/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReportContent.java new file mode 100644 index 0000000000..47e83525a3 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/DailyReportContent.java @@ -0,0 +1,135 @@ +package com.dianping.cat.core.dal; + + +public class DailyReportContent { + private long m_reportId; + + private byte[] m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyReportId; + + private double m_contentLength; + + private long m_startId; + + private long m_endId; + + private double m_capacity; + public void afterLoad() { + m_keyReportId = m_reportId; + } + + public double getCapacity() { + return m_capacity; + } + + public byte[] getContent() { + return m_content; + } + + public double getContentLength() { + return m_contentLength; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getEndId() { + return m_endId; + } + + public long getKeyReportId() { + return m_keyReportId; + } + + public long getReportId() { + return m_reportId; + } + + public long getStartId() { + return m_startId; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public DailyReportContent setCapacity(double capacity) { + m_capacity = capacity; + return this; + } + + public DailyReportContent setContent(byte[] content) { + m_content = content; + return this; + } + + public DailyReportContent setContentLength(double contentLength) { + m_contentLength = contentLength; + return this; + } + + public DailyReportContent setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public DailyReportContent setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public DailyReportContent setEndId(long endId) { + m_endId = endId; + return this; + } + + public DailyReportContent setKeyReportId(long keyReportId) { + m_keyReportId = keyReportId; + return this; + } + + public DailyReportContent setReportId(long reportId) { + m_reportId = reportId; + m_keyReportId = reportId; + return this; + } + + public DailyReportContent setStartId(long startId) { + m_startId = startId; + return this; + } + + public DailyReportContent setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("DailyReportContent["); + sb.append("capacity: ").append(m_capacity); + sb.append(", content: ").append(m_content == null ? null : java.util.Arrays.asList(m_content)); + sb.append(", content-length: ").append(m_contentLength); + sb.append(", create-time: ").append(m_createTime); + sb.append(", end-id: ").append(m_endId); + sb.append(", key-report-id: ").append(m_keyReportId); + sb.append(", report-id: ").append(m_reportId); + sb.append(", start-id: ").append(m_startId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/Hostinfo.java b/cat-core/src/main/java/com/dianping/cat/core/dal/Hostinfo.java new file mode 100644 index 0000000000..d6f838f062 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/Hostinfo.java @@ -0,0 +1,120 @@ +package com.dianping.cat.core.dal; + + +public class Hostinfo { + private long m_id; + + private String m_ip; + + private String m_domain; + + private String m_hostname; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public String getHostname() { + return m_hostname; + } + + public long getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public long getKeyId() { + return m_keyId; + } + + public java.util.Date getLastModifiedDate() { + return m_updateTime; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public Hostinfo setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public Hostinfo setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public Hostinfo setDomain(String domain) { + m_domain = domain; + return this; + } + + public Hostinfo setHostname(String hostname) { + m_hostname = hostname; + return this; + } + + public Hostinfo setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public Hostinfo setIp(String ip) { + m_ip = ip; + return this; + } + + public Hostinfo setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public Hostinfo setLastModifiedDate(java.util.Date lastModifiedDate) { + m_updateTime = lastModifiedDate; + return this; + } + + public Hostinfo setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("Hostinfo["); + sb.append("create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", hostname: ").append(m_hostname); + sb.append(", id: ").append(m_id); + sb.append(", ip: ").append(m_ip); + sb.append(", key-id: ").append(m_keyId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReport.java b/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReport.java new file mode 100644 index 0000000000..6903b6618b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReport.java @@ -0,0 +1,147 @@ +package com.dianping.cat.core.dal; + + +public class HourlyReport { + private long m_id; + + private int m_type; + + private String m_name; + + private String m_ip; + + private String m_domain; + + private java.util.Date m_period; + + private java.util.Date m_createTime; + + private long m_keyId; + + private java.util.Date m_startDate; + + private java.util.Date m_endDate; + public void afterLoad() { + m_keyId = m_id; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public java.util.Date getEndDate() { + return m_endDate; + } + + public long getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public long getKeyId() { + return m_keyId; + } + + public String getName() { + return m_name; + } + + public java.util.Date getPeriod() { + return m_period; + } + + public java.util.Date getStartDate() { + return m_startDate; + } + + public int getType() { + return m_type; + } + + public HourlyReport setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public HourlyReport setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public HourlyReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public HourlyReport setEndDate(java.util.Date endDate) { + m_endDate = endDate; + return this; + } + + public HourlyReport setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public HourlyReport setIp(String ip) { + m_ip = ip; + return this; + } + + public HourlyReport setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public HourlyReport setName(String name) { + m_name = name; + return this; + } + + public HourlyReport setPeriod(java.util.Date period) { + m_period = period; + return this; + } + + public HourlyReport setStartDate(java.util.Date startDate) { + m_startDate = startDate; + return this; + } + + public HourlyReport setType(int type) { + m_type = type; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("HourlyReport["); + sb.append("create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", end-date: ").append(m_endDate); + sb.append(", id: ").append(m_id); + sb.append(", ip: ").append(m_ip); + sb.append(", key-id: ").append(m_keyId); + sb.append(", name: ").append(m_name); + sb.append(", period: ").append(m_period); + sb.append(", start-date: ").append(m_startDate); + sb.append(", type: ").append(m_type); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReportContent.java b/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReportContent.java new file mode 100644 index 0000000000..93e46252ee --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/HourlyReportContent.java @@ -0,0 +1,135 @@ +package com.dianping.cat.core.dal; + + +public class HourlyReportContent { + private long m_reportId; + + private byte[] m_content; + + private java.util.Date m_period; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyReportId; + + private long m_contentLength; + + private long m_startId; + + private double m_capacity; + public void afterLoad() { + m_keyReportId = m_reportId; + } + + public double getCapacity() { + return m_capacity; + } + + public byte[] getContent() { + return m_content; + } + + public long getContentLength() { + return m_contentLength; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getKeyReportId() { + return m_keyReportId; + } + + public java.util.Date getPeriod() { + return m_period; + } + + public long getReportId() { + return m_reportId; + } + + public long getStartId() { + return m_startId; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public HourlyReportContent setCapacity(double capacity) { + m_capacity = capacity; + return this; + } + + public HourlyReportContent setContent(byte[] content) { + m_content = content; + return this; + } + + public HourlyReportContent setContentLength(long contentLength) { + m_contentLength = contentLength; + return this; + } + + public HourlyReportContent setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public HourlyReportContent setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public HourlyReportContent setKeyReportId(long keyReportId) { + m_keyReportId = keyReportId; + return this; + } + + public HourlyReportContent setPeriod(java.util.Date period) { + m_period = period; + return this; + } + + public HourlyReportContent setReportId(long reportId) { + m_reportId = reportId; + m_keyReportId = reportId; + return this; + } + + public HourlyReportContent setStartId(long startId) { + m_startId = startId; + return this; + } + + public HourlyReportContent setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("HourlyReportContent["); + sb.append("capacity: ").append(m_capacity); + sb.append(", content: ").append(m_content == null ? null : java.util.Arrays.asList(m_content)); + sb.append(", content-length: ").append(m_contentLength); + sb.append(", create-time: ").append(m_createTime); + sb.append(", key-report-id: ").append(m_keyReportId); + sb.append(", period: ").append(m_period); + sb.append(", report-id: ").append(m_reportId); + sb.append(", start-id: ").append(m_startId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReport.java b/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReport.java new file mode 100644 index 0000000000..5e52e788fc --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReport.java @@ -0,0 +1,123 @@ +package com.dianping.cat.core.dal; + + +public class MonthlyReport { + private long m_id; + + private String m_name; + + private String m_ip; + + private String m_domain; + + private java.util.Date m_period; + + private int m_type; + + private java.util.Date m_createTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public long getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public long getKeyId() { + return m_keyId; + } + + public String getName() { + return m_name; + } + + public java.util.Date getPeriod() { + return m_period; + } + + public int getType() { + return m_type; + } + + public MonthlyReport setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public MonthlyReport setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public MonthlyReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public MonthlyReport setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public MonthlyReport setIp(String ip) { + m_ip = ip; + return this; + } + + public MonthlyReport setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public MonthlyReport setName(String name) { + m_name = name; + return this; + } + + public MonthlyReport setPeriod(java.util.Date period) { + m_period = period; + return this; + } + + public MonthlyReport setType(int type) { + m_type = type; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("MonthlyReport["); + sb.append("create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", id: ").append(m_id); + sb.append(", ip: ").append(m_ip); + sb.append(", key-id: ").append(m_keyId); + sb.append(", name: ").append(m_name); + sb.append(", period: ").append(m_period); + sb.append(", type: ").append(m_type); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReportContent.java b/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReportContent.java new file mode 100644 index 0000000000..a0effba35d --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/MonthlyReportContent.java @@ -0,0 +1,123 @@ +package com.dianping.cat.core.dal; + + +public class MonthlyReportContent { + private long m_reportId; + + private byte[] m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyReportId; + + private double m_contentLength; + + private double m_capacity; + + private long m_startId; + public void afterLoad() { + m_keyReportId = m_reportId; + } + + public double getCapacity() { + return m_capacity; + } + + public byte[] getContent() { + return m_content; + } + + public double getContentLength() { + return m_contentLength; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getKeyReportId() { + return m_keyReportId; + } + + public long getReportId() { + return m_reportId; + } + + public long getStartId() { + return m_startId; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public MonthlyReportContent setCapacity(double capacity) { + m_capacity = capacity; + return this; + } + + public MonthlyReportContent setContent(byte[] content) { + m_content = content; + return this; + } + + public MonthlyReportContent setContentLength(double contentLength) { + m_contentLength = contentLength; + return this; + } + + public MonthlyReportContent setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public MonthlyReportContent setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public MonthlyReportContent setKeyReportId(long keyReportId) { + m_keyReportId = keyReportId; + return this; + } + + public MonthlyReportContent setReportId(long reportId) { + m_reportId = reportId; + m_keyReportId = reportId; + return this; + } + + public MonthlyReportContent setStartId(long startId) { + m_startId = startId; + return this; + } + + public MonthlyReportContent setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("MonthlyReportContent["); + sb.append("capacity: ").append(m_capacity); + sb.append(", content: ").append(m_content == null ? null : java.util.Arrays.asList(m_content)); + sb.append(", content-length: ").append(m_contentLength); + sb.append(", create-time: ").append(m_createTime); + sb.append(", key-report-id: ").append(m_keyReportId); + sb.append(", report-id: ").append(m_reportId); + sb.append(", start-id: ").append(m_startId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/Project.java b/cat-core/src/main/java/com/dianping/cat/core/dal/Project.java new file mode 100644 index 0000000000..bf5a6bef46 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/Project.java @@ -0,0 +1,180 @@ +package com.dianping.cat.core.dal; + + +public class Project { + private long m_id; + + private String m_domain; + + private String m_cmdbDomain; + + private int m_level; + + private String m_bu; + + private String m_cmdbProductline; + + private String m_owner; + + private String m_email; + + private String m_phone; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public String getBu() { + return m_bu; + } + + public String getCmdbDomain() { + return m_cmdbDomain; + } + + public String getCmdbProductline() { + return m_cmdbProductline; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public String getEmail() { + return m_email; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public int getLevel() { + return m_level; + } + + public java.util.Date getModifyDate() { + return m_updateTime; + } + + public String getOwner() { + return m_owner; + } + + public String getPhone() { + return m_phone; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public Project setBu(String bu) { + m_bu = bu; + return this; + } + + public Project setCmdbDomain(String cmdbDomain) { + m_cmdbDomain = cmdbDomain; + return this; + } + + public Project setCmdbProductline(String cmdbProductline) { + m_cmdbProductline = cmdbProductline; + return this; + } + + public Project setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public Project setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public Project setDomain(String domain) { + m_domain = domain; + return this; + } + + public Project setEmail(String email) { + m_email = email; + return this; + } + + public Project setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public Project setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public Project setLevel(int level) { + m_level = level; + return this; + } + + public Project setModifyDate(java.util.Date modifyDate) { + m_updateTime = modifyDate; + return this; + } + + public Project setOwner(String owner) { + m_owner = owner; + return this; + } + + public Project setPhone(String phone) { + m_phone = phone; + return this; + } + + public Project setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("Project["); + sb.append("bu: ").append(m_bu); + sb.append(", cmdb-domain: ").append(m_cmdbDomain); + sb.append(", cmdb-productline: ").append(m_cmdbProductline); + sb.append(", create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", email: ").append(m_email); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", level: ").append(m_level); + sb.append(", owner: ").append(m_owner); + sb.append(", phone: ").append(m_phone); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/Task.java b/cat-core/src/main/java/com/dianping/cat/core/dal/Task.java new file mode 100644 index 0000000000..1ce25e45be --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/Task.java @@ -0,0 +1,249 @@ +package com.dianping.cat.core.dal; + + +public class Task { + private long m_id; + + private String m_producer; + + private String m_consumer; + + private int m_failureCount; + + private String m_reportName; + + private String m_reportDomain; + + private java.util.Date m_reportPeriod; + + private int m_status; + + private int m_taskType; + + private java.util.Date m_createTime; + + private java.util.Date m_startTime; + + private java.util.Date m_endTime; + + private long m_keyId; + + private java.util.Date m_updateTime; + + private int m_count; + + private int m_startLimit; + + private int m_endLimit; + public void afterLoad() { + m_keyId = m_id; + } + + public String getConsumer() { + return m_consumer; + } + + public int getCount() { + return m_count; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public java.util.Date getEndDate() { + return m_endTime; + } + + public int getEndLimit() { + return m_endLimit; + } + + public int getFailureCount() { + return m_failureCount; + } + + public java.util.Date getEndTime() { + return m_endTime; + } + + public long getId() { + return m_id; + } + + public long getKeyId() { + return m_keyId; + } + + public String getProducer() { + return m_producer; + } + + public String getReportDomain() { + return m_reportDomain; + } + + public String getReportName() { + return m_reportName; + } + + public java.util.Date getReportPeriod() { + return m_reportPeriod; + } + + public java.util.Date getStartDate() { + return m_startTime; + } + + public int getStartLimit() { + return m_startLimit; + } + + public int getStatus() { + return m_status; + } + + public int getTaskType() { + return m_taskType; + } + + public java.util.Date getStartTime() { + return m_startTime; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public Task setConsumer(String consumer) { + m_consumer = consumer; + return this; + } + + public Task setCount(int count) { + m_count = count; + return this; + } + + public Task setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public Task setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public Task setEndDate(java.util.Date endDate) { + m_endTime = endDate; + return this; + } + + public Task setEndLimit(int endLimit) { + m_endLimit = endLimit; + return this; + } + + public Task setFailureCount(int failureCount) { + m_failureCount = failureCount; + return this; + } + + public Task setEndTime(java.util.Date endTime) { + m_endTime = endTime; + return this; + } + + public Task setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public Task setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public Task setProducer(String producer) { + m_producer = producer; + return this; + } + + public Task setReportDomain(String reportDomain) { + m_reportDomain = reportDomain; + return this; + } + + public Task setReportName(String reportName) { + m_reportName = reportName; + return this; + } + + public Task setReportPeriod(java.util.Date reportPeriod) { + m_reportPeriod = reportPeriod; + return this; + } + + public Task setStartDate(java.util.Date startDate) { + m_startTime = startDate; + return this; + } + + public Task setStartLimit(int startLimit) { + m_startLimit = startLimit; + return this; + } + + public Task setStatus(int status) { + m_status = status; + return this; + } + + public Task setTaskType(int taskType) { + m_taskType = taskType; + return this; + } + + public Task setStartTime(java.util.Date startTime) { + m_startTime = startTime; + return this; + } + + public Task setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("Task["); + sb.append("consumer: ").append(m_consumer); + sb.append(", count: ").append(m_count); + sb.append(", create-time: ").append(m_createTime); + sb.append(", end-time: ").append(m_endTime); + sb.append(", end-limit: ").append(m_endLimit); + sb.append(", failure-count: ").append(m_failureCount); + sb.append(", id: ").append(m_id); + sb.append(", key-id: ").append(m_keyId); + sb.append(", producer: ").append(m_producer); + sb.append(", report-domain: ").append(m_reportDomain); + sb.append(", report-name: ").append(m_reportName); + sb.append(", report-period: ").append(m_reportPeriod); + sb.append(", start-time: ").append(m_startTime); + sb.append(", start-limit: ").append(m_startLimit); + sb.append(", status: ").append(m_status); + sb.append(", task-type: ").append(m_taskType); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReport.java b/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReport.java new file mode 100644 index 0000000000..e8b139992f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReport.java @@ -0,0 +1,123 @@ +package com.dianping.cat.core.dal; + + +public class WeeklyReport { + private long m_id; + + private String m_name; + + private String m_ip; + + private String m_domain; + + private java.util.Date m_period; + + private int m_type; + + private java.util.Date m_createTime; + + private long m_keyId; + public void afterLoad() { + m_keyId = m_id; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public String getDomain() { + return m_domain; + } + + public long getId() { + return m_id; + } + + public String getIp() { + return m_ip; + } + + public long getKeyId() { + return m_keyId; + } + + public String getName() { + return m_name; + } + + public java.util.Date getPeriod() { + return m_period; + } + + public int getType() { + return m_type; + } + + public WeeklyReport setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public WeeklyReport setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public WeeklyReport setDomain(String domain) { + m_domain = domain; + return this; + } + + public WeeklyReport setId(long id) { + m_id = id; + m_keyId = id; + return this; + } + + public WeeklyReport setIp(String ip) { + m_ip = ip; + return this; + } + + public WeeklyReport setKeyId(long keyId) { + m_keyId = keyId; + return this; + } + + public WeeklyReport setName(String name) { + m_name = name; + return this; + } + + public WeeklyReport setPeriod(java.util.Date period) { + m_period = period; + return this; + } + + public WeeklyReport setType(int type) { + m_type = type; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("WeeklyReport["); + sb.append("create-time: ").append(m_createTime); + sb.append(", domain: ").append(m_domain); + sb.append(", id: ").append(m_id); + sb.append(", ip: ").append(m_ip); + sb.append(", key-id: ").append(m_keyId); + sb.append(", name: ").append(m_name); + sb.append(", period: ").append(m_period); + sb.append(", type: ").append(m_type); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReportContent.java b/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReportContent.java new file mode 100644 index 0000000000..0d5037024f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/core/dal/WeeklyReportContent.java @@ -0,0 +1,123 @@ +package com.dianping.cat.core.dal; + + +public class WeeklyReportContent { + private long m_reportId; + + private byte[] m_content; + + private java.util.Date m_createTime; + + private java.util.Date m_updateTime; + + private long m_keyReportId; + + private double m_contentLength; + + private double m_capacity; + + private long m_startId; + public void afterLoad() { + m_keyReportId = m_reportId; + } + + public double getCapacity() { + return m_capacity; + } + + public byte[] getContent() { + return m_content; + } + + public double getContentLength() { + return m_contentLength; + } + + public java.util.Date getCreationDate() { + return m_createTime; + } + + public java.util.Date getCreateTime() { + return m_createTime; + } + + public long getKeyReportId() { + return m_keyReportId; + } + + public long getReportId() { + return m_reportId; + } + + public long getStartId() { + return m_startId; + } + + public java.util.Date getUpdateTime() { + return m_updateTime; + } + + public WeeklyReportContent setCapacity(double capacity) { + m_capacity = capacity; + return this; + } + + public WeeklyReportContent setContent(byte[] content) { + m_content = content; + return this; + } + + public WeeklyReportContent setContentLength(double contentLength) { + m_contentLength = contentLength; + return this; + } + + public WeeklyReportContent setCreationDate(java.util.Date creationDate) { + m_createTime = creationDate; + return this; + } + + public WeeklyReportContent setCreateTime(java.util.Date createTime) { + m_createTime = createTime; + return this; + } + + public WeeklyReportContent setKeyReportId(long keyReportId) { + m_keyReportId = keyReportId; + return this; + } + + public WeeklyReportContent setReportId(long reportId) { + m_reportId = reportId; + m_keyReportId = reportId; + return this; + } + + public WeeklyReportContent setStartId(long startId) { + m_startId = startId; + return this; + } + + public WeeklyReportContent setUpdateTime(java.util.Date updateTime) { + m_updateTime = updateTime; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(1024); + + sb.append("WeeklyReportContent["); + sb.append("capacity: ").append(m_capacity); + sb.append(", content: ").append(m_content == null ? null : java.util.Arrays.asList(m_content)); + sb.append(", content-length: ").append(m_contentLength); + sb.append(", create-time: ").append(m_createTime); + sb.append(", key-report-id: ").append(m_keyReportId); + sb.append(", report-id: ").append(m_reportId); + sb.append(", start-id: ").append(m_startId); + sb.append(", update-time: ").append(m_updateTime); + sb.append("]"); + return sb.toString(); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/helper/JsonBuilder.java b/cat-core/src/main/java/com/dianping/cat/helper/JsonBuilder.java index b81503ed5e..7709b25c12 100644 --- a/cat-core/src/main/java/com/dianping/cat/helper/JsonBuilder.java +++ b/cat-core/src/main/java/com/dianping/cat/helper/JsonBuilder.java @@ -36,9 +36,7 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; -import org.unidal.lookup.annotation.Named; -@Named public class JsonBuilder { private FieldNamingStrategy m_fieldNamingStrategy = new FieldNamingStrategy() { diff --git a/cat-core/src/main/java/com/dianping/cat/message/DefaultPathBuilder.java b/cat-core/src/main/java/com/dianping/cat/message/DefaultPathBuilder.java index da4530dc75..bb3231520d 100644 --- a/cat-core/src/main/java/com/dianping/cat/message/DefaultPathBuilder.java +++ b/cat-core/src/main/java/com/dianping/cat/message/DefaultPathBuilder.java @@ -18,13 +18,10 @@ */ package com.dianping.cat.message; -import java.text.MessageFormat; -import java.util.Date; - -import org.unidal.lookup.annotation.Named; - -@Named(type = PathBuilder.class) -public class DefaultPathBuilder implements PathBuilder { +import java.text.MessageFormat; +import java.util.Date; + +public class DefaultPathBuilder implements PathBuilder { @Override public String getLogviewPath(Date timestamp, String name) { diff --git a/cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java b/cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java index d0c52124ff..a0e08347bb 100644 --- a/cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java +++ b/cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java @@ -168,6 +168,7 @@ protected Message decodeLine(Context ctx, DefaultTransaction parent, Stack parts = Splitters.by(',').split(str); + List parts = Arrays.asList(str.split(",")); int len = parts.size(); int[] segments = new int[len]; @@ -311,7 +311,7 @@ private int[] getTransactionDurationSegments(Transaction t) { str = data.substring(3, pos); } - List parts = Splitters.by(',').split(str); + List parts = Arrays.asList(str.split(",")); int len = parts.size(); int[] segments = new int[len]; diff --git a/cat-core/src/main/java/com/dianping/cat/message/spi/DefaultMessageTree.java b/cat-core/src/main/java/com/dianping/cat/message/spi/DefaultMessageTree.java index 37b46432a5..8a11508d65 100644 --- a/cat-core/src/main/java/com/dianping/cat/message/spi/DefaultMessageTree.java +++ b/cat-core/src/main/java/com/dianping/cat/message/spi/DefaultMessageTree.java @@ -133,11 +133,13 @@ public MessageTree copyForTest() { try { PlainTextMessageCodec codec = new PlainTextMessageCodec(); buf = codec.encode(this); - //buf.readInt(); // get rid of length + buf.readInt(); // get rid of length return codec.decode(buf); } catch (Exception ex) { Cat.logError(ex); + } finally { + BufReleaseHelper.release(buf); } return null; diff --git a/cat-core/src/main/java/com/dianping/cat/message/storage/LocalMessageBucket.java b/cat-core/src/main/java/com/dianping/cat/message/storage/LocalMessageBucket.java index 2f6e26784f..c80b6a86ed 100644 --- a/cat-core/src/main/java/com/dianping/cat/message/storage/LocalMessageBucket.java +++ b/cat-core/src/main/java/com/dianping/cat/message/storage/LocalMessageBucket.java @@ -28,14 +28,12 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; -import org.unidal.lookup.annotation.Named; import org.xerial.snappy.SnappyOutputStream; import com.dianping.cat.message.CodecHandler; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.message.tree.MessageId; -@Named(type = MessageBucket.class, value = LocalMessageBucket.ID, instantiationStrategy = Named.PER_LOOKUP) public class LocalMessageBucket implements MessageBucket { public static final String ID = "local"; diff --git a/cat-core/src/main/java/com/dianping/cat/message/storage/MessageBucketFactory.java b/cat-core/src/main/java/com/dianping/cat/message/storage/MessageBucketFactory.java new file mode 100644 index 0000000000..0af4d2813b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/message/storage/MessageBucketFactory.java @@ -0,0 +1,9 @@ +package com.dianping.cat.message.storage; + +import java.io.File; +import java.io.IOException; + +public interface MessageBucketFactory { + + public LocalMessageBucket createBucket(File baseDir, String dataFile) throws IOException; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportModel.java b/cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportModel.java index 69bed7f085..2a73f647d2 100755 --- a/cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportModel.java +++ b/cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportModel.java @@ -27,13 +27,11 @@ import java.util.List; import java.util.Map; -import org.unidal.lookup.ContainerLoader; import org.unidal.web.mvc.Action; import org.unidal.web.mvc.ActionContext; import org.unidal.web.mvc.Page; import org.unidal.web.mvc.ViewModel; -import com.dianping.cat.Cat; import com.dianping.cat.config.sample.SampleConfigManager; import com.dianping.cat.helper.JsonBuilder; import com.dianping.cat.sample.entity.Domain; @@ -43,7 +41,6 @@ public abstract class AbstractReportModel> extends ViewModel { - private transient Date m_creatTime; private transient String m_customDate; @@ -70,13 +67,22 @@ public abstract class AbstractReportModel 0; + } + } diff --git a/cat-core/src/main/java/com/dianping/cat/mvc/PayloadNormalizer.java b/cat-core/src/main/java/com/dianping/cat/mvc/PayloadNormalizer.java index 291fa9a428..9ac225b98c 100644 --- a/cat-core/src/main/java/com/dianping/cat/mvc/PayloadNormalizer.java +++ b/cat-core/src/main/java/com/dianping/cat/mvc/PayloadNormalizer.java @@ -20,16 +20,11 @@ import java.util.Date; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.helper.TimeHelper; -@Named public class PayloadNormalizer { - @Inject protected ServerConfigManager m_manager; @SuppressWarnings("rawtypes") @@ -59,4 +54,8 @@ public void normalize(AbstractReportModel model, AbstractReportPayload payload) } } + public void setManager(ServerConfigManager manager) { + m_manager = manager; + } + } diff --git a/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencies.java b/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencies.java new file mode 100644 index 0000000000..247d8c781c --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencies.java @@ -0,0 +1,39 @@ +package com.dianping.cat.mvc; + +import com.dianping.cat.config.sample.SampleConfigManager; +import com.dianping.cat.service.HostinfoService; +import com.dianping.cat.service.ProjectService; + +public class ReportModelDependencies { + private final HostinfoService m_hostinfoService; + + private final ProjectService m_projectService; + + private final SampleConfigManager m_sampleConfigManager; + + public ReportModelDependencies(ProjectService projectService, HostinfoService hostinfoService, + SampleConfigManager sampleConfigManager) { + m_projectService = requireNonNull(projectService, ProjectService.class); + m_hostinfoService = requireNonNull(hostinfoService, HostinfoService.class); + m_sampleConfigManager = requireNonNull(sampleConfigManager, SampleConfigManager.class); + } + + public HostinfoService getHostinfoService() { + return m_hostinfoService; + } + + public ProjectService getProjectService() { + return m_projectService; + } + + public SampleConfigManager getSampleConfigManager() { + return m_sampleConfigManager; + } + + private T requireNonNull(T value, Class type) { + if (value == null) { + throw new IllegalArgumentException(type.getName() + " is required for report model dependencies."); + } + return value; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencyProvider.java b/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencyProvider.java new file mode 100644 index 0000000000..24d8c64bff --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mvc/ReportModelDependencyProvider.java @@ -0,0 +1,8 @@ +package com.dianping.cat.mvc; + +public interface ReportModelDependencyProvider { + + ReportModelDependencies getReportModelDependencies(); + + void setReportModelDependencies(ReportModelDependencies dependencies); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/ConfigRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/ConfigRepository.java new file mode 100644 index 0000000000..066c6f2d58 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/ConfigRepository.java @@ -0,0 +1,145 @@ +package com.dianping.cat.mybatis; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.config.Config; +import com.dianping.cat.mybatis.mapper.ConfigMapper; +import com.dianping.cat.mybatis.data.ConfigDO; + +public class ConfigRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public Config createLocal() { + return new Config(); + } + + public int deleteByPK(Config proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteById(proto.getKeyId())); + } + + public List findAllConfig() { + ConfigMapper mapper = springMapper(); + + return mapper.queryAll().stream().map(this::toConfig).collect(Collectors.toList()); + } + + public Config findByName(String name) { + ConfigMapper mapper = springMapper(); + + return requireFound(mapper.findByName(name), "name", name); + } + + public Config findByPK(int keyId) { + return findByPK((long) keyId); + } + + public Config findByPK(long keyId) { + ConfigMapper mapper = springMapper(); + + return requireFound(mapper.findById(keyId), "id", String.valueOf(keyId)); + } + + public int insert(Config proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + Date now = new Date(); + + if (proto.getCreationDate() == null) { + proto.setCreationDate(now); + } + if (proto.getModifyDate() == null) { + proto.setModifyDate(now); + } + + ConfigDO config = toConfigDO(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(config)); + + proto.setId(config.getId()); + proto.setKeyId(config.getId()); + return count; + } + + public int updateByPK(Config proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + proto.setModifyDate(new Date()); + return transactionTemplate.execute(status -> springMapper().updateById(toConfigDO(proto))); + } + + private ConfigMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for ConfigMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("ConfigRepository is using Spring managed ConfigMapper."); + } + + return sqlSessionTemplate.getMapper(ConfigMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for ConfigMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private Config requireFound(ConfigDO config, String field, String value) { + if (config == null) { + throw new EmptyResultDataAccessException(String.format("No config found by %s(%s).", field, value), 1); + } + + return toConfig(config); + } + + private Config toConfig(ConfigDO configDO) { + Config config = new Config(); + + config.setId(configDO.getId()); + config.setName(configDO.getName()); + config.setContent(configDO.getContent()); + config.setCreateTime(configDO.getCreateTime()); + config.setUpdateTime(configDO.getUpdateTime()); + config.afterLoad(); + return config; + } + + private ConfigDO toConfigDO(Config config) { + ConfigDO configDO = new ConfigDO(); + + configDO.setId(config.getKeyId() > 0 ? config.getKeyId() : config.getId()); + configDO.setName(config.getName()); + configDO.setContent(config.getContent()); + configDO.setCreateTime(config.getCreateTime()); + configDO.setUpdateTime(config.getUpdateTime()); + return configDO; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportContentRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportContentRepository.java new file mode 100644 index 0000000000..701a1bab01 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportContentRepository.java @@ -0,0 +1,152 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.DailyReportContent; +import com.dianping.cat.mybatis.mapper.DailyReportContentMapper; +import com.dianping.cat.mybatis.data.DailyReportContentDO; + +public class DailyReportContentRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(DailyReportContentRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public DailyReportContent createLocal() { + return new DailyReportContent(); + } + + public int deleteByPK(DailyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyReportId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for DailyReportContent.", e); + } + } + + public List findOverloadReport(long startId) { + DailyReportContentMapper mapper = springMapper(); + DailyReportContentDO record = new DailyReportContentDO(); + + record.setStartId(startId); + try { + return mapper.findOverloadReport(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing findOverloadReport for DailyReportContent.", e); + } + } + + public DailyReportContent findByPK(long keyReportId) { + DailyReportContentMapper mapper = springMapper(); + + try { + return requireFound(mapper.findByPrimaryKey(keyReportId), "primary key", String.valueOf(keyReportId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for DailyReportContent.", e); + } + } + + public int insert(DailyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().insert(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for DailyReportContent.", e); + } + } + + public int updateByPK(DailyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for DailyReportContent.", e); + } + } + + private DailyReportContentMapper springMapper() { + if (m_sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for DailyReportContentMapper."); + } + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("DailyReportContentRepository is using Spring managed DailyReportContentMapper."); + } + return m_sqlSessionTemplate.getMapper(DailyReportContentMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for DailyReportContentMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private DailyReportContent requireFound(DailyReportContentDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No DailyReportContent found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private DailyReportContent toModel(DailyReportContentDO record) { + DailyReportContent model = new DailyReportContent(); + + if (record.getReportId() != null) { + model.setReportId(record.getReportId()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getContentLength() != null) { + model.setContentLength(record.getContentLength()); + } + model.afterLoad(); + return model; + } + + private DailyReportContentDO toRecord(DailyReportContent model) { + DailyReportContentDO record = new DailyReportContentDO(); + + record.setReportId(model.getReportId()); + record.setContent(model.getContent()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyReportId(model.getKeyReportId()); + record.setStartId(model.getStartId()); + record.setEndId(model.getEndId()); + record.setCapacity(model.getCapacity()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportRepository.java new file mode 100644 index 0000000000..5ec161ed1c --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/DailyReportRepository.java @@ -0,0 +1,145 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.DailyReport; +import com.dianping.cat.mybatis.mapper.DailyReportMapper; +import com.dianping.cat.mybatis.data.DailyReportDO; + +public class DailyReportRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(DailyReportRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public DailyReport createLocal() { + return new DailyReport(); + } + + public int deleteByDomainNamePeriod(DailyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByDomainNamePeriod(proto.getDomain(), + proto.getName(), proto.getPeriod())); + } + + public int deleteByPK(DailyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteById(proto.getKeyId())); + } + + public DailyReport findByDomainNamePeriod(String domain, String name, java.util.Date period) { + DailyReportMapper mapper = springMapper(); + + return requireFound(mapper.findByDomainNamePeriod(domain, name, period), "domain/name/period", + domain + "/" + name + "/" + period); + } + + public DailyReport findByPK(long keyId) { + DailyReportMapper mapper = springMapper(); + + return requireFound(mapper.findById(keyId), "id", String.valueOf(keyId)); + } + + public int insert(DailyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + DailyReportDO report = toDailyReportDO(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(report)); + + proto.setId(report.getId()); + proto.setKeyId(report.getId()); + return count; + } + + public List queryLatestReportsByDomainName(String domain, String name, int limits) { + DailyReportMapper mapper = springMapper(); + + return mapper.queryLatestReportsByDomainName(domain, name, limits).stream() + .map(this::toDailyReport) + .collect(Collectors.toList()); + } + + public int updateByPK(DailyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateById(toDailyReportDO(proto))); + } + + private DailyReportMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for DailyReportMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("DailyReportRepository is using Spring managed DailyReportMapper."); + } + + return sqlSessionTemplate.getMapper(DailyReportMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for DailyReportMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private DailyReport requireFound(DailyReportDO report, String field, String value) { + if (report == null) { + throw new EmptyResultDataAccessException(String.format("No daily report found by %s(%s).", field, value), 1); + } + + return toDailyReport(report); + } + + private DailyReport toDailyReport(DailyReportDO reportDO) { + DailyReport report = new DailyReport(); + + report.setId(reportDO.getId()); + report.setName(reportDO.getName()); + report.setIp(reportDO.getIp()); + report.setDomain(reportDO.getDomain()); + report.setPeriod(reportDO.getPeriod()); + report.setType(reportDO.getType()); + report.setCreateTime(reportDO.getCreateTime()); + report.afterLoad(); + return report; + } + + private DailyReportDO toDailyReportDO(DailyReport report) { + DailyReportDO reportDO = new DailyReportDO(); + + reportDO.setId(report.getKeyId() > 0 ? report.getKeyId() : report.getId()); + reportDO.setName(report.getName()); + reportDO.setIp(report.getIp()); + reportDO.setDomain(report.getDomain()); + reportDO.setPeriod(report.getPeriod()); + reportDO.setType(report.getType()); + reportDO.setCreateTime(report.getCreateTime()); + return reportDO; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/HostInfoRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/HostInfoRepository.java new file mode 100644 index 0000000000..621298e0a4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/HostInfoRepository.java @@ -0,0 +1,162 @@ +package com.dianping.cat.mybatis; + +import java.util.Date; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.Hostinfo; +import com.dianping.cat.mybatis.mapper.HostInfoMapper; +import com.dianping.cat.mybatis.data.HostInfoDO; + +public class HostInfoRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(HostInfoRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public Hostinfo createLocal() { + return new Hostinfo(); + } + + public int deleteByPK(Hostinfo proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public List findAllIp() { + HostInfoMapper mapper = springMapper(); + + HostInfoDO record = new HostInfoDO(); + + return mapper.findAllIp(record).stream().map(this::toModel).collect(Collectors.toList()); + } + + public Hostinfo findByPK(long keyId) { + HostInfoMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public Hostinfo findByIp(String ip) { + HostInfoMapper mapper = springMapper(); + HostInfoDO record = new HostInfoDO(); + + record.setIp(ip); + HostInfoDO result = mapper.findByIp(record).stream().findFirst().orElse(null); + + return requireFound(result, "findByIp", record.toString()); + } + + public int insert(Hostinfo proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + Date now = new Date(); + + if (proto.getCreationDate() == null) { + proto.setCreationDate(now); + } + if (proto.getLastModifiedDate() == null) { + proto.setLastModifiedDate(now); + } + + HostInfoDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(Hostinfo proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + private HostInfoMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for HostinfoMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("HostinfoRepository is using Spring managed HostinfoMapper."); + } + + return sqlSessionTemplate.getMapper(HostInfoMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for HostinfoMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private Hostinfo requireFound(HostInfoDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No Hostinfo found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private Hostinfo toModel(HostInfoDO record) { + Hostinfo model = new Hostinfo(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getIp() != null) { + model.setIp(record.getIp()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getHostname() != null) { + model.setHostname(record.getHostname()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + model.afterLoad(); + return model; + } + + private HostInfoDO toRecord(Hostinfo model) { + HostInfoDO record = new HostInfoDO(); + + record.setId(model.getId()); + record.setIp(model.getIp()); + record.setDomain(model.getDomain()); + record.setHostname(model.getHostname()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + return record; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportContentRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportContentRepository.java new file mode 100644 index 0000000000..12ab0eaa30 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportContentRepository.java @@ -0,0 +1,155 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.HourlyReportContent; +import com.dianping.cat.mybatis.mapper.HourlyReportContentMapper; +import com.dianping.cat.mybatis.data.HourlyReportContentDO; + +public class HourlyReportContentRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(HourlyReportContentRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public HourlyReportContent createLocal() { + return new HourlyReportContent(); + } + + public int deleteByPK(HourlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyReportId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for HourlyReportContent.", e); + } + } + + public List findOverloadReport(long startId) { + HourlyReportContentMapper mapper = springMapper(); + HourlyReportContentDO record = new HourlyReportContentDO(); + + record.setStartId(startId); + try { + return mapper.findOverloadReport(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing findOverloadReport for HourlyReportContent.", e); + } + } + + public HourlyReportContent findByPK(long keyReportId, java.util.Date period) { + HourlyReportContentMapper mapper = springMapper(); + + try { + return requireFound(mapper.findByPrimaryKey(keyReportId), "primary key", String.valueOf(keyReportId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for HourlyReportContent.", e); + } + } + + public int insert(HourlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().insert(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for HourlyReportContent.", e); + } + } + + public int updateByPK(HourlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for HourlyReportContent.", e); + } + } + + private HourlyReportContentMapper springMapper() { + if (m_sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for HourlyReportContentMapper."); + } + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("HourlyReportContentRepository is using Spring managed HourlyReportContentMapper."); + } + return m_sqlSessionTemplate.getMapper(HourlyReportContentMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for HourlyReportContentMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private HourlyReportContent requireFound(HourlyReportContentDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No HourlyReportContent found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private HourlyReportContent toModel(HourlyReportContentDO record) { + HourlyReportContent model = new HourlyReportContent(); + + if (record.getReportId() != null) { + model.setReportId(record.getReportId()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getPeriod() != null) { + model.setPeriod(record.getPeriod()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getContentLength() != null) { + model.setContentLength(record.getContentLength().longValue()); + } + model.afterLoad(); + return model; + } + + private HourlyReportContentDO toRecord(HourlyReportContent model) { + HourlyReportContentDO record = new HourlyReportContentDO(); + + record.setReportId(model.getReportId()); + record.setContent(model.getContent()); + record.setPeriod(model.getPeriod()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyReportId(model.getKeyReportId()); + record.setStartId(model.getStartId()); + record.setCapacity(model.getCapacity()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportRepository.java new file mode 100644 index 0000000000..4d891bb1a9 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/HourlyReportRepository.java @@ -0,0 +1,157 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.HourlyReport; +import com.dianping.cat.mybatis.mapper.HourlyReportMapper; +import com.dianping.cat.mybatis.data.HourlyReportDO; + +public class HourlyReportRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(HourlyReportRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public HourlyReport createLocal() { + return new HourlyReport(); + } + + public int deleteByPK(HourlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public List findAllByDomainNamePeriod(java.util.Date period, String domain, String name) { + HourlyReportDO record = new HourlyReportDO(); + HourlyReportMapper mapper = springMapper(); + + record.setPeriod(period); + record.setDomain(domain); + record.setName(name); + return mapper.findAllByDomainNamePeriod(record).stream().map(this::toModel).collect(Collectors.toList()); + } + + public List findAllByPeriodName(java.util.Date period, String name) { + HourlyReportDO record = new HourlyReportDO(); + HourlyReportMapper mapper = springMapper(); + + record.setPeriod(period); + record.setName(name); + return mapper.findAllByPeriodName(record).stream().map(this::toModel).collect(Collectors.toList()); + } + + public HourlyReport findByPK(long keyId) { + HourlyReportMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public int insert(HourlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + HourlyReportDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(HourlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + private HourlyReportMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for HourlyreportMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("HourlyReportRepository is using Spring managed HourlyreportMapper."); + } + + return sqlSessionTemplate.getMapper(HourlyReportMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for HourlyreportMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private HourlyReport requireFound(HourlyReportDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No HourlyReport found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private HourlyReport toModel(HourlyReportDO record) { + HourlyReport model = new HourlyReport(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getType() != null) { + model.setType(record.getType()); + } + if (record.getName() != null) { + model.setName(record.getName()); + } + if (record.getIp() != null) { + model.setIp(record.getIp()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getPeriod() != null) { + model.setPeriod(record.getPeriod()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + model.afterLoad(); + return model; + } + + private HourlyReportDO toRecord(HourlyReport model) { + HourlyReportDO record = new HourlyReportDO(); + + record.setId(model.getId()); + record.setType(model.getType()); + record.setName(model.getName()); + record.setIp(model.getIp()); + record.setDomain(model.getDomain()); + record.setPeriod(model.getPeriod()); + record.setCreateTime(model.getCreateTime()); + record.setKeyId(model.getKeyId()); + return record; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportContentRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportContentRepository.java new file mode 100644 index 0000000000..9d594d33ea --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportContentRepository.java @@ -0,0 +1,151 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.MonthlyReportContent; +import com.dianping.cat.mybatis.mapper.MonthlyReportContentMapper; +import com.dianping.cat.mybatis.data.MonthlyReportContentDO; + +public class MonthlyReportContentRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(MonthlyReportContentRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public MonthlyReportContent createLocal() { + return new MonthlyReportContent(); + } + + public int deleteByPK(MonthlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyReportId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for MonthlyReportContent.", e); + } + } + + public List findOverloadReport(long startId) { + MonthlyReportContentMapper mapper = springMapper(); + MonthlyReportContentDO record = new MonthlyReportContentDO(); + + record.setStartId(startId); + try { + return mapper.findOverloadReport(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing findOverloadReport for MonthlyReportContent.", e); + } + } + + public MonthlyReportContent findByPK(long keyReportId) { + MonthlyReportContentMapper mapper = springMapper(); + + try { + return requireFound(mapper.findByPrimaryKey(keyReportId), "primary key", String.valueOf(keyReportId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for MonthlyReportContent.", e); + } + } + + public int insert(MonthlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().insert(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for MonthlyReportContent.", e); + } + } + + public int updateByPK(MonthlyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for MonthlyReportContent.", e); + } + } + + private MonthlyReportContentMapper springMapper() { + if (m_sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for MonthlyReportContentMapper."); + } + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("MonthlyReportContentRepository is using Spring managed MonthlyReportContentMapper."); + } + return m_sqlSessionTemplate.getMapper(MonthlyReportContentMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for MonthlyReportContentMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private MonthlyReportContent requireFound(MonthlyReportContentDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No MonthlyReportContent found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private MonthlyReportContent toModel(MonthlyReportContentDO record) { + MonthlyReportContent model = new MonthlyReportContent(); + + if (record.getReportId() != null) { + model.setReportId(record.getReportId()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getContentLength() != null) { + model.setContentLength(record.getContentLength()); + } + model.afterLoad(); + return model; + } + + private MonthlyReportContentDO toRecord(MonthlyReportContent model) { + MonthlyReportContentDO record = new MonthlyReportContentDO(); + + record.setReportId(model.getReportId()); + record.setContent(model.getContent()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyReportId(model.getKeyReportId()); + record.setCapacity(model.getCapacity()); + record.setStartId(model.getStartId()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportRepository.java new file mode 100644 index 0000000000..945c153f02 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/MonthlyReportRepository.java @@ -0,0 +1,154 @@ +package com.dianping.cat.mybatis; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.MonthlyReport; +import com.dianping.cat.mybatis.mapper.MonthReportMapper; +import com.dianping.cat.mybatis.data.MonthReportDO; + +public class MonthlyReportRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(MonthlyReportRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public MonthlyReport createLocal() { + return new MonthlyReport(); + } + + public int deleteByPK(MonthlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public int deleteReportByDomainNamePeriod(MonthlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteReportByDomainNamePeriod(toRecord(proto))); + } + + public MonthlyReport findByPK(long keyId) { + MonthReportMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public MonthlyReport findReportByDomainNamePeriod(java.util.Date period, String domain, String name) { + MonthReportDO record = new MonthReportDO(); + MonthReportMapper mapper = springMapper(); + + record.setPeriod(period); + record.setDomain(domain); + record.setName(name); + MonthReportDO result = mapper.findReportByDomainNamePeriod(record).stream().findFirst().orElse(null); + + return requireFound(result, "findReportByDomainNamePeriod", record.toString()); + } + + public int insert(MonthlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + MonthReportDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(MonthlyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + private MonthReportMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for MonthreportMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("MonthlyReportRepository is using Spring managed MonthreportMapper."); + } + + return sqlSessionTemplate.getMapper(MonthReportMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for MonthreportMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private MonthlyReport requireFound(MonthReportDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No MonthlyReport found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private MonthlyReport toModel(MonthReportDO record) { + MonthlyReport model = new MonthlyReport(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getName() != null) { + model.setName(record.getName()); + } + if (record.getIp() != null) { + model.setIp(record.getIp()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getPeriod() != null) { + model.setPeriod(record.getPeriod()); + } + if (record.getType() != null) { + model.setType(record.getType()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + model.afterLoad(); + return model; + } + + private MonthReportDO toRecord(MonthlyReport model) { + MonthReportDO record = new MonthReportDO(); + + record.setId(model.getId()); + record.setName(model.getName()); + record.setIp(model.getIp()); + record.setDomain(model.getDomain()); + record.setPeriod(model.getPeriod()); + record.setType(model.getType()); + record.setCreateTime(model.getCreateTime()); + record.setKeyId(model.getKeyId()); + return record; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/ProjectRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/ProjectRepository.java new file mode 100644 index 0000000000..3843406a4a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/ProjectRepository.java @@ -0,0 +1,187 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.Project; +import com.dianping.cat.mybatis.mapper.ProjectMapper; +import com.dianping.cat.mybatis.data.ProjectDO; + +public class ProjectRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public Project createLocal() { + return new Project(); + } + + public int deleteByPK(Project proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public List findAll() { + ProjectMapper mapper = springMapper(); + + ProjectDO record = new ProjectDO(); + + return mapper.findAll(record).stream().map(this::toModel).collect(Collectors.toList()); + } + + public Project findByPK(int keyId) { + return findByPK((long) keyId); + } + + public Project findByPK(long keyId) { + ProjectMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public Project findByDomain(String domain) { + ProjectDO record = new ProjectDO(); + ProjectMapper mapper = springMapper(); + + record.setDomain(domain); + ProjectDO result = mapper.findByDomain(record).stream().findFirst().orElse(null); + + return requireFound(result, "findByDomain", record.toString()); + } + + public Project findByCmdbDomain(String domain) { + ProjectDO record = new ProjectDO(); + ProjectMapper mapper = springMapper(); + + record.setDomain(domain); + ProjectDO result = mapper.findByCmdbDomain(record).stream().findFirst().orElse(null); + + return requireFound(result, "findByCmdbDomain", record.toString()); + } + + public int insert(Project proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + ProjectDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(Project proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + private ProjectMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for ProjectMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("ProjectRepository is using Spring managed ProjectMapper."); + } + + return sqlSessionTemplate.getMapper(ProjectMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for ProjectMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private Project requireFound(ProjectDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No Project found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private Project toModel(ProjectDO record) { + Project model = new Project(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getCmdbDomain() != null) { + model.setCmdbDomain(record.getCmdbDomain()); + } + if (record.getLevel() != null) { + model.setLevel(record.getLevel()); + } + if (record.getBu() != null) { + model.setBu(record.getBu()); + } + if (record.getCmdbProductline() != null) { + model.setCmdbProductline(record.getCmdbProductline()); + } + if (record.getOwner() != null) { + model.setOwner(record.getOwner()); + } + if (record.getEmail() != null) { + model.setEmail(record.getEmail()); + } + if (record.getPhone() != null) { + model.setPhone(record.getPhone()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + model.afterLoad(); + return model; + } + + private ProjectDO toRecord(Project model) { + ProjectDO record = new ProjectDO(); + + record.setId(model.getId()); + record.setDomain(model.getDomain()); + record.setCmdbDomain(model.getCmdbDomain()); + record.setLevel(model.getLevel()); + record.setBu(model.getBu()); + record.setCmdbProductline(model.getCmdbProductline()); + record.setOwner(model.getOwner()); + record.setEmail(Optional.ofNullable(model.getEmail()).orElse("")); + record.setPhone(Optional.ofNullable(model.getPhone()).orElse( "")); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + return record; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/SpringBackedRepositorySupport.java b/cat-core/src/main/java/com/dianping/cat/mybatis/SpringBackedRepositorySupport.java new file mode 100644 index 0000000000..0abae1cb63 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/SpringBackedRepositorySupport.java @@ -0,0 +1,54 @@ +package com.dianping.cat.mybatis; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.springframework.transaction.support.TransactionTemplate; + +public abstract class SpringBackedRepositorySupport { + private final Class m_mapperClass; + + private final String m_springMapperMessage; + + private final AtomicBoolean m_springMapperLogged = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + protected SpringBackedRepositorySupport(Class mapperClass, String mapperResource, + String springMapperMessage) { + m_mapperClass = mapperClass; + m_springMapperMessage = springMapperMessage; + } + + protected T springMapper(Logger logger) { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for " + + m_mapperClass.getName() + "."); + } + if (m_springMapperLogged.compareAndSet(false, true)) { + logger.info(m_springMapperMessage); + } + return sqlSessionTemplate.getMapper(m_mapperClass); + } + + protected TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for " + + m_mapperClass.getName() + "."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/TaskRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/TaskRepository.java new file mode 100644 index 0000000000..c71ea07aa1 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/TaskRepository.java @@ -0,0 +1,205 @@ +package com.dianping.cat.mybatis; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.Task; +import com.dianping.cat.mybatis.mapper.TaskMapper; +import com.dianping.cat.mybatis.data.TaskDO; + +public class TaskRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(TaskRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public Task createLocal() { + return new Task(); + } + + public int deleteByPK(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public Task findByPK(int keyId) { + return findByPK((long) keyId); + } + + public Task findByPK(long keyId) { + TaskMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public Task findByStatusConsumer(int status, String consumer) { + TaskMapper mapper = springMapper(); + TaskDO record = new TaskDO(); + + record.setStatus(status); + record.setConsumer(consumer); + TaskDO result = mapper.findByStatusConsumer(record).stream().findFirst().orElse(null); + + return result == null ? null : toModel(result); + } + + public int insert(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + TaskDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + public int updateTodoToDoing(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateTodoToDoing(toRecord(proto))); + } + + public int updateDoingToDone(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateDoingToDone(toRecord(proto))); + } + + public int updateFailureToDone(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateFailureToDone(toRecord(proto))); + } + + public int updateStatusToTodo(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateStatusToTodo(toRecord(proto))); + } + + public int updateDoingToFail(Task proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateDoingToFail(toRecord(proto))); + } + + private TaskMapper springMapper() { + if (m_sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for TaskMapper."); + } + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("TaskRepository is using Spring managed TaskMapper."); + } + return m_sqlSessionTemplate.getMapper(TaskMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for TaskMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private Task requireFound(TaskDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No Task found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private Task toModel(TaskDO record) { + Task model = new Task(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getProducer() != null) { + model.setProducer(record.getProducer()); + } + if (record.getConsumer() != null) { + model.setConsumer(record.getConsumer()); + } + if (record.getFailureCount() != null) { + model.setFailureCount(record.getFailureCount()); + } + if (record.getReportName() != null) { + model.setReportName(record.getReportName()); + } + if (record.getReportDomain() != null) { + model.setReportDomain(record.getReportDomain()); + } + if (record.getReportPeriod() != null) { + model.setReportPeriod(record.getReportPeriod()); + } + if (record.getStatus() != null) { + model.setStatus(record.getStatus()); + } + if (record.getTaskType() != null) { + model.setTaskType(record.getTaskType()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getStartTime() != null) { + model.setStartTime(record.getStartTime()); + } + if (record.getEndTime() != null) { + model.setEndTime(record.getEndTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getCount() != null) { + model.setCount(record.getCount()); + } + model.afterLoad(); + return model; + } + + private TaskDO toRecord(Task model) { + TaskDO record = new TaskDO(); + + record.setId(model.getId()); + record.setProducer(model.getProducer()); + record.setConsumer(model.getConsumer()); + record.setFailureCount(model.getFailureCount()); + record.setReportName(model.getReportName()); + record.setReportDomain(model.getReportDomain()); + record.setReportPeriod(model.getReportPeriod()); + record.setStatus(model.getStatus()); + record.setTaskType(model.getTaskType()); + record.setCreateTime(model.getCreateTime()); + record.setStartTime(model.getStartTime()); + record.setEndTime(model.getEndTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + record.setStartLimit(model.getStartLimit()); + record.setEndLimit(model.getEndLimit()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportContentRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportContentRepository.java new file mode 100644 index 0000000000..6b7b63d3a3 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportContentRepository.java @@ -0,0 +1,151 @@ +package com.dianping.cat.mybatis; + +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.WeeklyReportContent; +import com.dianping.cat.mybatis.mapper.WeeklyReportContentMapper; +import com.dianping.cat.mybatis.data.WeeklyReportContentDO; + +public class WeeklyReportContentRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(WeeklyReportContentRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public WeeklyReportContent createLocal() { + return new WeeklyReportContent(); + } + + public int deleteByPK(WeeklyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyReportId())); + } catch (Exception e) { + throw new IllegalStateException("Error when executing deleteByPK for WeeklyReportContent.", e); + } + } + + public List findOverloadReport(long startId) { + WeeklyReportContentMapper mapper = springMapper(); + WeeklyReportContentDO record = new WeeklyReportContentDO(); + + record.setStartId(startId); + try { + return mapper.findOverloadReport(record).stream().map(this::toModel).collect(Collectors.toList()); + } catch (Exception e) { + throw new IllegalStateException("Error when executing findOverloadReport for WeeklyReportContent.", e); + } + } + + public WeeklyReportContent findByPK(long keyReportId) { + WeeklyReportContentMapper mapper = springMapper(); + + try { + return requireFound(mapper.findByPrimaryKey(keyReportId), "primary key", String.valueOf(keyReportId)); + } catch (EmptyResultDataAccessException e) { + throw e; + } catch (Exception e) { + throw new IllegalStateException("Error when executing findByPK for WeeklyReportContent.", e); + } + } + + public int insert(WeeklyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().insert(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing insert for WeeklyReportContent.", e); + } + } + + public int updateByPK(WeeklyReportContent proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + try { + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } catch (Exception e) { + throw new IllegalStateException("Error when executing updateByPK for WeeklyReportContent.", e); + } + } + + private WeeklyReportContentMapper springMapper() { + if (m_sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for WeeklyReportContentMapper."); + } + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("WeeklyReportContentRepository is using Spring managed WeeklyReportContentMapper."); + } + return m_sqlSessionTemplate.getMapper(WeeklyReportContentMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for WeeklyReportContentMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private WeeklyReportContent requireFound(WeeklyReportContentDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No WeeklyReportContent found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private WeeklyReportContent toModel(WeeklyReportContentDO record) { + WeeklyReportContent model = new WeeklyReportContent(); + + if (record.getReportId() != null) { + model.setReportId(record.getReportId()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + if (record.getUpdateTime() != null) { + model.setUpdateTime(record.getUpdateTime()); + } + if (record.getContentLength() != null) { + model.setContentLength(record.getContentLength()); + } + model.afterLoad(); + return model; + } + + private WeeklyReportContentDO toRecord(WeeklyReportContent model) { + WeeklyReportContentDO record = new WeeklyReportContentDO(); + + record.setReportId(model.getReportId()); + record.setContent(model.getContent()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyReportId(model.getKeyReportId()); + record.setCapacity(model.getCapacity()); + record.setStartId(model.getStartId()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportRepository.java new file mode 100644 index 0000000000..813570ddb0 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/WeeklyReportRepository.java @@ -0,0 +1,154 @@ +package com.dianping.cat.mybatis; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.mybatis.spring.SqlSessionTemplate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.dal.WeeklyReport; +import com.dianping.cat.mybatis.mapper.WeeklyReportMapper; +import com.dianping.cat.mybatis.data.WeeklyReportDO; + +public class WeeklyReportRepository { + private static final Logger LOGGER = LoggerFactory.getLogger(WeeklyReportRepository.class); + + private static final AtomicBoolean SPRING_MAPPER_LOGGED = new AtomicBoolean(); + + private SqlSessionTemplate m_sqlSessionTemplate; + + private TransactionTemplate m_transactionTemplate; + + public WeeklyReport createLocal() { + return new WeeklyReport(); + } + + public int deleteByPK(WeeklyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteByPrimaryKey(proto.getKeyId())); + } + + public int deleteReportByDomainNamePeriod(WeeklyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().deleteReportByDomainNamePeriod(toRecord(proto))); + } + + public WeeklyReport findByPK(long keyId) { + WeeklyReportMapper mapper = springMapper(); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public WeeklyReport findReportByDomainNamePeriod(java.util.Date period, String domain, String name) { + WeeklyReportDO record = new WeeklyReportDO(); + WeeklyReportMapper mapper = springMapper(); + + record.setPeriod(period); + record.setDomain(domain); + record.setName(name); + WeeklyReportDO result = mapper.findReportByDomainNamePeriod(record).stream().findFirst().orElse(null); + + return requireFound(result, "findReportByDomainNamePeriod", record.toString()); + } + + public int insert(WeeklyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + WeeklyReportDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper().insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(WeeklyReport proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper().updateByPrimaryKey(toRecord(proto))); + } + + private WeeklyReportMapper springMapper() { + SqlSessionTemplate sqlSessionTemplate = m_sqlSessionTemplate; + + if (sqlSessionTemplate == null) { + throw new IllegalStateException("Spring SqlSessionTemplate is not configured for WeeklyreportMapper."); + } + + if (SPRING_MAPPER_LOGGED.compareAndSet(false, true)) { + LOGGER.info("WeeklyReportRepository is using Spring managed WeeklyreportMapper."); + } + + return sqlSessionTemplate.getMapper(WeeklyReportMapper.class); + } + + private TransactionTemplate springTransactionTemplate() { + if (m_transactionTemplate == null) { + throw new IllegalStateException("Spring TransactionTemplate is not configured for WeeklyreportMapper."); + } + return m_transactionTemplate; + } + + public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { + m_sqlSessionTemplate = sqlSessionTemplate; + } + + public void setTransactionTemplate(TransactionTemplate transactionTemplate) { + m_transactionTemplate = transactionTemplate; + } + + private WeeklyReport requireFound(WeeklyReportDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No WeeklyReport found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private WeeklyReport toModel(WeeklyReportDO record) { + WeeklyReport model = new WeeklyReport(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getName() != null) { + model.setName(record.getName()); + } + if (record.getIp() != null) { + model.setIp(record.getIp()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getPeriod() != null) { + model.setPeriod(record.getPeriod()); + } + if (record.getType() != null) { + model.setType(record.getType()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + model.afterLoad(); + return model; + } + + private WeeklyReportDO toRecord(WeeklyReport model) { + WeeklyReportDO record = new WeeklyReportDO(); + + record.setId(model.getId()); + record.setName(model.getName()); + record.setIp(model.getIp()); + record.setDomain(model.getDomain()); + record.setPeriod(model.getPeriod()); + record.setType(model.getType()); + record.setCreateTime(model.getCreateTime()); + record.setKeyId(model.getKeyId()); + return record; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessConfigDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessConfigDO.java new file mode 100644 index 0000000000..eab759c214 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessConfigDO.java @@ -0,0 +1,50 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BusinessConfigDO { + private Long id; + + private String name; + + private String domain; + + private String content; + + private Date createTime; + + private Date updateTime; + + private Long keyId; + + public Date getUpdatetime() { + return updateTime; + } + + public void setId(Integer id) { + this.id = id == null ? null : id.longValue(); + } + + public void setId(Long id) { + this.id = id; + } + + public void setKeyId(Integer keyId) { + this.keyId = keyId == null ? null : keyId.longValue(); + } + + public void setKeyId(Long keyId) { + this.keyId = keyId; + } + + public void setUpdatetime(Date updatetime) { + updateTime = updatetime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessReportDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessReportDO.java new file mode 100644 index 0000000000..fa060a290b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/BusinessReportDO.java @@ -0,0 +1,26 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class BusinessReportDO { + private Long id; + + private Integer type; + + private String name; + + private String ip; + + private String productLine; + + private Date period; + + private byte[] content; + + private Date createTime; + + private Date updateTime; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/ConfigDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/ConfigDO.java new file mode 100644 index 0000000000..ad6e879d5a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/ConfigDO.java @@ -0,0 +1,18 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class ConfigDO { + private Long id; + + private String name; + + private String content; + + private Date createTime; + + private Date updateTime; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportContentDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportContentDO.java new file mode 100644 index 0000000000..ddfd01310f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportContentDO.java @@ -0,0 +1,28 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class DailyReportContentDO { + private Long reportId; + + private byte[] content; + + private Date period; + + private Date createTime; + + private Date updateTime; + + private Double contentLength; + + private Long keyReportId; + + private Long startId; + + private Long endId; + + private Double capacity; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportDO.java new file mode 100644 index 0000000000..fa9037e6b0 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/DailyReportDO.java @@ -0,0 +1,22 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class DailyReportDO { + private Long id; + + private String name; + + private String ip; + + private String domain; + + private Date period; + + private Integer type; + + private Date createTime; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/HostInfoDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HostInfoDO.java new file mode 100644 index 0000000000..53f3b3532f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HostInfoDO.java @@ -0,0 +1,22 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class HostInfoDO { + private Long id; + + private String ip; + + private String domain; + + private String hostname; + + private Date createTime; + + private Date updateTime; + + private Long keyId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportContentDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportContentDO.java new file mode 100644 index 0000000000..d69d080af4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportContentDO.java @@ -0,0 +1,26 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class HourlyReportContentDO { + private Long reportId; + + private byte[] content; + + private Date period; + + private Date createTime; + + private Date updateTime; + + private Double contentLength; + + private Long keyReportId; + + private Long startId; + + private Double capacity; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportDO.java new file mode 100644 index 0000000000..36480074e3 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/HourlyReportDO.java @@ -0,0 +1,24 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class HourlyReportDO { + private Long id; + + private Integer type; + + private String name; + + private String ip; + + private String domain; + + private Date period; + + private Date createTime; + + private Long keyId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthReportDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthReportDO.java new file mode 100644 index 0000000000..3c643a6190 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthReportDO.java @@ -0,0 +1,24 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class MonthReportDO { + private Long id; + + private String name; + + private String ip; + + private String domain; + + private Date period; + + private Integer type; + + private Date createTime; + + private Long keyId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthlyReportContentDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthlyReportContentDO.java new file mode 100644 index 0000000000..8854334780 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/MonthlyReportContentDO.java @@ -0,0 +1,26 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class MonthlyReportContentDO { + private Long reportId; + + private byte[] content; + + private Date period; + + private Date createTime; + + private Date updateTime; + + private Double contentLength; + + private Long keyReportId; + + private Double capacity; + + private Long startId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/OperationDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/OperationDO.java new file mode 100644 index 0000000000..141bd7053e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/OperationDO.java @@ -0,0 +1,50 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class OperationDO { + private Long id; + + private String user; + + private String module; + + private String operation; + + private Date operationTime; + + private String content; + + private Date createTime; + + private Date updateTime; + + private Long keyId; + + public Date getCreationDate() { + return createTime; + } + + public Date getTime() { + return operationTime; + } + + public void setCreationDate(Date creationDate) { + createTime = creationDate; + } + + public void setId(Integer id) { + this.id = id == null ? null : id.longValue(); + } + + public void setId(Long id) { + this.id = id; + } + + public void setTime(Date time) { + operationTime = time; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/ProjectDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/ProjectDO.java new file mode 100644 index 0000000000..78d4e51000 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/ProjectDO.java @@ -0,0 +1,32 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class ProjectDO { + private Long id; + + private String domain; + + private String cmdbDomain; + + private Integer level; + + private String bu; + + private String cmdbProductline; + + private String owner; + + private String email; + + private String phone; + + private Date createTime; + + private Date updateTime; + + private Long keyId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/TaskDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/TaskDO.java new file mode 100644 index 0000000000..a1f0d8f768 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/TaskDO.java @@ -0,0 +1,42 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class TaskDO { + private Long id; + + private String producer; + + private String consumer; + + private Integer failureCount; + + private String reportName; + + private String reportDomain; + + private Date reportPeriod; + + private Integer status; + + private Integer taskType; + + private Date createTime; + + private Date startTime; + + private Date endTime; + + private Date updateTime; + + private Integer count; + + private Long keyId; + + private Integer startLimit; + + private Integer endLimit; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportContentDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportContentDO.java new file mode 100644 index 0000000000..46b46f5dec --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportContentDO.java @@ -0,0 +1,26 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class WeeklyReportContentDO { + private Long reportId; + + private byte[] content; + + private Date period; + + private Date createTime; + + private Date updateTime; + + private Double contentLength; + + private Long keyReportId; + + private Double capacity; + + private Long startId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportDO.java b/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportDO.java new file mode 100644 index 0000000000..f955c68504 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/data/WeeklyReportDO.java @@ -0,0 +1,24 @@ +package com.dianping.cat.mybatis.data; + +import java.util.Date; + +import lombok.Data; + +@Data +public class WeeklyReportDO { + private Long id; + + private String name; + + private String ip; + + private String domain; + + private Date period; + + private Integer type; + + private Date createTime; + + private Long keyId; +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigMapper.java new file mode 100644 index 0000000000..14ec94a261 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigMapper.java @@ -0,0 +1,25 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.BusinessConfigDO; + +public interface BusinessConfigMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + BusinessConfigDO findByPrimaryKey(@Param("id") Long id); + + int insert(BusinessConfigDO record); + + List queryAll(); + + int updateByPrimaryKey(BusinessConfigDO record); + + List findByNameDomain(@Param("record") BusinessConfigDO record); + + List findByName(@Param("record") BusinessConfigDO record); + + int updateBaseConfigByDomain(@Param("record") BusinessConfigDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigRepository.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigRepository.java new file mode 100644 index 0000000000..d568598fe6 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessConfigRepository.java @@ -0,0 +1,132 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.transaction.support.TransactionTemplate; + +import com.dianping.cat.core.config.BusinessConfig; +import com.dianping.cat.mybatis.data.BusinessConfigDO; +import com.dianping.cat.mybatis.SpringBackedRepositorySupport; + +public class BusinessConfigRepository extends SpringBackedRepositorySupport { + private static final Logger LOGGER = LoggerFactory.getLogger(BusinessConfigRepository.class); + + private static final String MAPPER_RESOURCE = "mybatis/mapper/BusinessConfigMapper.xml"; + + public BusinessConfigRepository() { + super(BusinessConfigMapper.class, MAPPER_RESOURCE, + "BusinessConfigRepository is using Spring managed BusinessConfigMapper."); + } + + public BusinessConfig createLocal() { + return new BusinessConfig(); + } + + public int deleteByPK(BusinessConfig proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper(LOGGER).deleteByPrimaryKey(proto.getKeyId())); + } + + public List findByName(String name) { + BusinessConfigMapper mapper = springMapper(LOGGER); + BusinessConfigDO record = new BusinessConfigDO(); + + record.setName(name); + return mapper.findByName(record).stream().map(this::toModel).collect(Collectors.toList()); + } + + public BusinessConfig findByPK(int keyId) { + return findByPK((long) keyId); + } + + public BusinessConfig findByPK(long keyId) { + BusinessConfigMapper mapper = springMapper(LOGGER); + + return requireFound(mapper.findByPrimaryKey(keyId), "primary key", String.valueOf(keyId)); + } + + public BusinessConfig findByNameDomain(String name, String domain) { + BusinessConfigMapper mapper = springMapper(LOGGER); + BusinessConfigDO record = new BusinessConfigDO(); + + record.setName(name); + record.setDomain(domain); + BusinessConfigDO result = mapper.findByNameDomain(record).stream().findFirst().orElse(null); + + return requireFound(result, "findByNameDomain", record.toString()); + } + + public int insert(BusinessConfig proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + BusinessConfigDO record = toRecord(proto); + int count = transactionTemplate.execute(status -> springMapper(LOGGER).insert(record)); + + proto.setId(record.getId()); + proto.setKeyId(record.getId()); + return count; + } + + public int updateByPK(BusinessConfig proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper(LOGGER).updateByPrimaryKey(toRecord(proto))); + } + + public int updateBaseConfigByDomain(BusinessConfig proto) { + TransactionTemplate transactionTemplate = springTransactionTemplate(); + + return transactionTemplate.execute(status -> springMapper(LOGGER).updateBaseConfigByDomain(toRecord(proto))); + } + + private BusinessConfig requireFound(BusinessConfigDO record, String field, String value) { + if (record == null) { + throw new EmptyResultDataAccessException("No BusinessConfig found by " + field + "(" + value + ").", 1); + } + + return toModel(record); + } + + private BusinessConfig toModel(BusinessConfigDO record) { + BusinessConfig model = new BusinessConfig(); + + if (record.getId() != null) { + model.setId(record.getId()); + } + if (record.getName() != null) { + model.setName(record.getName()); + } + if (record.getDomain() != null) { + model.setDomain(record.getDomain()); + } + if (record.getContent() != null) { + model.setContent(record.getContent()); + } + if (record.getUpdatetime() != null) { + model.setUpdatetime(record.getUpdatetime()); + } + if (record.getCreateTime() != null) { + model.setCreateTime(record.getCreateTime()); + } + model.afterLoad(); + return model; + } + + private BusinessConfigDO toRecord(BusinessConfig model) { + BusinessConfigDO record = new BusinessConfigDO(); + + record.setId(model.getId()); + record.setName(model.getName()); + record.setDomain(model.getDomain()); + record.setContent(model.getContent()); + record.setCreateTime(model.getCreateTime()); + record.setUpdateTime(model.getUpdateTime()); + record.setKeyId(model.getKeyId()); + return record; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessReportMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessReportMapper.java new file mode 100644 index 0000000000..81c1c3f3dd --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/BusinessReportMapper.java @@ -0,0 +1,19 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.BusinessReportDO; + +public interface BusinessReportMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + BusinessReportDO findByPrimaryKey(@Param("id") Long id); + + int insert(BusinessReportDO record); + + List queryAll(); + + int updateByPrimaryKey(BusinessReportDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ConfigMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ConfigMapper.java new file mode 100644 index 0000000000..4c53a0b6ac --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ConfigMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.ConfigDO; + +public interface ConfigMapper { + int deleteById(@Param("id") Long id); + + ConfigDO findById(@Param("id") Long id); + + ConfigDO findByName(@Param("name") String name); + + List queryAll(); + + int insert(ConfigDO config); + + int updateById(ConfigDO config); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportContentMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportContentMapper.java new file mode 100644 index 0000000000..f9d1d48707 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportContentMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.DailyReportContentDO; + +public interface DailyReportContentMapper { + int deleteByPrimaryKey(@Param("reportId") Long reportId); + + DailyReportContentDO findByPrimaryKey(@Param("reportId") Long reportId); + + int insert(DailyReportContentDO record); + + List queryAll(); + + int updateByPrimaryKey(DailyReportContentDO record); + + List findOverloadReport(@Param("record") DailyReportContentDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportMapper.java new file mode 100644 index 0000000000..d49f7d144c --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/DailyReportMapper.java @@ -0,0 +1,27 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.Date; +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.DailyReportDO; + +public interface DailyReportMapper { + int deleteByDomainNamePeriod(@Param("domain") String domain, @Param("name") String name, + @Param("period") Date period); + + int deleteById(@Param("id") Long id); + + DailyReportDO findByDomainNamePeriod(@Param("domain") String domain, @Param("name") String name, + @Param("period") Date period); + + DailyReportDO findById(@Param("id") Long id); + + int insert(DailyReportDO report); + + List queryLatestReportsByDomainName(@Param("domain") String domain, @Param("name") String name, + @Param("limits") int limits); + + int updateById(DailyReportDO report); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HostInfoMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HostInfoMapper.java new file mode 100644 index 0000000000..40582edf9a --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HostInfoMapper.java @@ -0,0 +1,23 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.HostInfoDO; + +public interface HostInfoMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + HostInfoDO findByPrimaryKey(@Param("id") Long id); + + int insert(HostInfoDO record); + + List queryAll(); + + int updateByPrimaryKey(HostInfoDO record); + + List findByIp(@Param("record") HostInfoDO record); + + List findAllIp(@Param("record") HostInfoDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportContentMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportContentMapper.java new file mode 100644 index 0000000000..ebbbe4a4c6 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportContentMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.HourlyReportContentDO; + +public interface HourlyReportContentMapper { + int deleteByPrimaryKey(@Param("reportId") Long reportId); + + HourlyReportContentDO findByPrimaryKey(@Param("reportId") Long reportId); + + int insert(HourlyReportContentDO record); + + List queryAll(); + + int updateByPrimaryKey(HourlyReportContentDO record); + + List findOverloadReport(@Param("record") HourlyReportContentDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportMapper.java new file mode 100644 index 0000000000..6d8703891e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/HourlyReportMapper.java @@ -0,0 +1,23 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.HourlyReportDO; + +public interface HourlyReportMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + HourlyReportDO findByPrimaryKey(@Param("id") Long id); + + int insert(HourlyReportDO record); + + List queryAll(); + + int updateByPrimaryKey(HourlyReportDO record); + + List findAllByDomainNamePeriod(@Param("record") HourlyReportDO record); + + List findAllByPeriodName(@Param("record") HourlyReportDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthReportMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthReportMapper.java new file mode 100644 index 0000000000..3fc3c99e89 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthReportMapper.java @@ -0,0 +1,23 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.MonthReportDO; + +public interface MonthReportMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + MonthReportDO findByPrimaryKey(@Param("id") Long id); + + int insert(MonthReportDO record); + + List queryAll(); + + int updateByPrimaryKey(MonthReportDO record); + + List findReportByDomainNamePeriod(@Param("record") MonthReportDO record); + + int deleteReportByDomainNamePeriod(@Param("record") MonthReportDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthlyReportContentMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthlyReportContentMapper.java new file mode 100644 index 0000000000..3cf6bf6293 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/MonthlyReportContentMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.MonthlyReportContentDO; + +public interface MonthlyReportContentMapper { + int deleteByPrimaryKey(@Param("reportId") Long reportId); + + MonthlyReportContentDO findByPrimaryKey(@Param("reportId") Long reportId); + + int insert(MonthlyReportContentDO record); + + List queryAll(); + + int updateByPrimaryKey(MonthlyReportContentDO record); + + List findOverloadReport(@Param("record") MonthlyReportContentDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/OperationMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/OperationMapper.java new file mode 100644 index 0000000000..a404a61c2e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/OperationMapper.java @@ -0,0 +1,19 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.OperationDO; + +public interface OperationMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + OperationDO findByPrimaryKey(@Param("id") Long id); + + int insert(OperationDO record); + + List queryAll(); + + int updateByPrimaryKey(OperationDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ProjectMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ProjectMapper.java new file mode 100644 index 0000000000..d6f62e012b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/ProjectMapper.java @@ -0,0 +1,25 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.ProjectDO; + +public interface ProjectMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + ProjectDO findByPrimaryKey(@Param("id") Long id); + + int insert(ProjectDO record); + + List queryAll(); + + int updateByPrimaryKey(ProjectDO record); + + List findAll(@Param("record") ProjectDO record); + + List findByDomain(@Param("record") ProjectDO record); + + List findByCmdbDomain(@Param("record") ProjectDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/TaskMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/TaskMapper.java new file mode 100644 index 0000000000..55ae6e05d9 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/TaskMapper.java @@ -0,0 +1,31 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.TaskDO; + +public interface TaskMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + TaskDO findByPrimaryKey(@Param("id") Long id); + + int insert(TaskDO record); + + List queryAll(); + + int updateByPrimaryKey(TaskDO record); + + List findByStatusConsumer(@Param("record") TaskDO record); + + int updateTodoToDoing(@Param("record") TaskDO record); + + int updateDoingToDone(@Param("record") TaskDO record); + + int updateFailureToDone(@Param("record") TaskDO record); + + int updateStatusToTodo(@Param("record") TaskDO record); + + int updateDoingToFail(@Param("record") TaskDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportContentMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportContentMapper.java new file mode 100644 index 0000000000..e74ba7ecb4 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportContentMapper.java @@ -0,0 +1,21 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.WeeklyReportContentDO; + +public interface WeeklyReportContentMapper { + int deleteByPrimaryKey(@Param("reportId") Long reportId); + + WeeklyReportContentDO findByPrimaryKey(@Param("reportId") Long reportId); + + int insert(WeeklyReportContentDO record); + + List queryAll(); + + int updateByPrimaryKey(WeeklyReportContentDO record); + + List findOverloadReport(@Param("record") WeeklyReportContentDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportMapper.java b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportMapper.java new file mode 100644 index 0000000000..a60bc1b8ad --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/mybatis/mapper/WeeklyReportMapper.java @@ -0,0 +1,23 @@ +package com.dianping.cat.mybatis.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; + +import com.dianping.cat.mybatis.data.WeeklyReportDO; + +public interface WeeklyReportMapper { + int deleteByPrimaryKey(@Param("id") Long id); + + WeeklyReportDO findByPrimaryKey(@Param("id") Long id); + + int insert(WeeklyReportDO record); + + List queryAll(); + + int updateByPrimaryKey(WeeklyReportDO record); + + List findReportByDomainNamePeriod(@Param("record") WeeklyReportDO record); + + int deleteReportByDomainNamePeriod(@Param("record") WeeklyReportDO record); +} diff --git a/cat-core/src/main/java/com/dianping/cat/report/DefaultReportBucketManager.java b/cat-core/src/main/java/com/dianping/cat/report/DefaultReportBucketManager.java index 258563c95e..e3f609fc48 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/DefaultReportBucketManager.java +++ b/cat-core/src/main/java/com/dianping/cat/report/DefaultReportBucketManager.java @@ -20,60 +20,54 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Files; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Set; +import java.util.stream.Stream; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.helper.Scanners; -import org.unidal.helper.Scanners.FileMatcher; -import org.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.Event; import com.dianping.cat.message.Transaction; -@Named(type = ReportBucketManager.class) -public class DefaultReportBucketManager extends ContainerHolder implements ReportBucketManager, Initializable { +public class DefaultReportBucketManager implements ReportBucketManager { + private static final Logger LOGGER = LoggerFactory.getLogger(DefaultReportBucketManager.class); - @Inject private ServerConfigManager m_configManager; + private ReportBucketFactory m_bucketFactory; + + private Set m_factoryBuckets = Collections.synchronizedSet( + Collections.newSetFromMap(new IdentityHashMap())); + private File m_reportBaseDir; + private volatile boolean m_initialized; + @Override public void clearOldReports() { + initialize(); + Transaction t = Cat.newTransaction("System", "DeleteReport"); try { final List toRemovePaths = new ArrayList(); final Set validPaths = queryValidPath(m_configManager.getLocalReportStroageTime()); - Scanners.forDir().scan(m_reportBaseDir, new FileMatcher() { - @Override - public Direction matches(File base, String path) { - File file = new File(base, path); - if (file.isFile() && shouldDeleteReport(path)) { - toRemovePaths.add(path); - } - return Direction.DOWN; - } - - private boolean shouldDeleteReport(String path) { - for (String str : validPaths) { - if (path.contains(str)) { - return false; - } - } - return true; + for (String path : listRelativeFiles(m_reportBaseDir)) { + if (shouldDeleteReport(path, validPaths)) { + toRemovePaths.add(path); } - }); + } for (String path : toRemovePaths) { File file = new File(m_reportBaseDir, path); @@ -95,24 +89,44 @@ public void closeBucket(ReportBucket bucket) { try { bucket.close(); } catch (Exception e) { - // ignore it + LOGGER.warn("Unable to close report bucket, bucket={}.", bucket, e); } finally { - release(bucket); + if (m_factoryBuckets.remove(bucket)) { + LOGGER.debug("Closed Spring-created report bucket, bucket={}.", bucket); + } else { + LOGGER.debug("Closed externally-created report bucket, bucket={}.", bucket); + } } } @Override public ReportBucket getReportBucket(long timestamp, String name, int index) throws IOException { + initialize(); + Date date = new Date(timestamp); - ReportBucket bucket = lookup(ReportBucket.class); - bucket.initialize(name, date, index); + if (m_bucketFactory == null) { + throw new IllegalStateException("ReportBucketFactory is required for report storage."); + } + ReportBucket bucket = m_bucketFactory.createReportBucket(name, date, index); + + m_factoryBuckets.add(bucket); return bucket; } - @Override - public void initialize() throws InitializationException { - m_reportBaseDir = new File(Cat.getCatHome(), "bucket/report"); + public synchronized void initialize() { + if (!m_initialized) { + if (m_configManager == null) { + throw new IllegalStateException("ServerConfigManager is required for report bucket manager."); + } + if (m_bucketFactory == null) { + throw new IllegalStateException("ReportBucketFactory is required for report bucket manager."); + } + m_reportBaseDir = new File(Cat.getCatHome(), "bucket/report"); + LOGGER.info("Initialized report bucket manager, baseDir={}, springBucketFactoryConfigured={}.", + m_reportBaseDir.getAbsolutePath(), m_bucketFactory != null); + m_initialized = true; + } } private Set queryValidPath(int day) { @@ -128,22 +142,49 @@ private Set queryValidPath(int day) { return strs; } + private List listRelativeDirectories(File baseFile) { + List paths = new ArrayList(); + + if (baseFile == null || !baseFile.exists()) { + return paths; + } + + try (Stream stream = Files.walk(baseFile.toPath())) { + stream.filter(path -> !path.equals(baseFile.toPath())) + .filter(Files::isDirectory) + .map(path -> relativePath(baseFile, path)) + .forEach(paths::add); + } catch (IOException e) { + Cat.logError(e); + } + return paths; + } + + private List listRelativeFiles(File baseFile) { + List paths = new ArrayList(); + + if (baseFile == null || !baseFile.exists()) { + return paths; + } + + try (Stream stream = Files.walk(baseFile.toPath())) { + stream.filter(Files::isRegularFile) + .map(path -> relativePath(baseFile, path)) + .forEach(paths::add); + } catch (IOException e) { + Cat.logError(e); + } + return paths; + } + + private String relativePath(File baseFile, Path path) { + return baseFile.toPath().relativize(path).toString().replace(File.separatorChar, '/'); + } + private void removeEmptyDir(File baseFile) { // the path has two depth for (int i = 0; i < 2; i++) { - final List directionPaths = new ArrayList(); - - Scanners.forDir().scan(baseFile, new FileMatcher() { - @Override - public Direction matches(File base, String path) { - if (new File(base, path).isDirectory()) { - directionPaths.add(path); - } - - return Direction.DOWN; - } - }); - for (String path : directionPaths) { + for (String path : listRelativeDirectories(baseFile)) { try { File file = new File(baseFile, path); @@ -154,4 +195,21 @@ public Direction matches(File base, String path) { } } + private boolean shouldDeleteReport(String path, Set validPaths) { + for (String str : validPaths) { + if (path.contains(str)) { + return false; + } + } + return true; + } + + public void setBucketFactory(ReportBucketFactory bucketFactory) { + m_bucketFactory = bucketFactory; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + } diff --git a/cat-core/src/main/java/com/dianping/cat/report/DefaultReportManager.java b/cat-core/src/main/java/com/dianping/cat/report/DefaultReportManager.java index f1cc0fc53a..77b157d8f5 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/DefaultReportManager.java +++ b/cat-core/src/main/java/com/dianping/cat/report/DefaultReportManager.java @@ -28,18 +28,14 @@ import java.util.Set; 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.unidal.lookup.ContainerHolder; -import org.unidal.lookup.annotation.Inject; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.configuration.NetworkInterfaceManager; import com.dianping.cat.core.dal.HourlyReport; import com.dianping.cat.core.dal.HourlyReportContent; -import com.dianping.cat.core.dal.HourlyReportContentDao; -import com.dianping.cat.core.dal.HourlyReportDao; +import com.dianping.cat.mybatis.HourlyReportContentRepository; +import com.dianping.cat.mybatis.HourlyReportRepository; import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; @@ -49,28 +45,23 @@ * Hourly report manager by domain of one report type(such as Transaction, Event, Problem, Heartbeat etc.) produced in one machine * for a couple of hours. */ -public class DefaultReportManager extends ContainerHolder implements ReportManager, Initializable, LogEnabled { - @Inject +public class DefaultReportManager implements ReportManager { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DefaultReportManager.class); + private ReportDelegate m_reportDelegate; - @Inject private ReportBucketManager m_bucketManager; - @Inject - private HourlyReportDao m_reportDao; + private HourlyReportRepository m_reportDao; - @Inject - private HourlyReportContentDao m_reportContentDao; + private HourlyReportContentRepository m_reportContentDao; - @Inject private DomainValidator m_validator; private String m_name; private Map> m_reports = new ConcurrentHashMap>(); - private Logger m_logger; - public void cleanup(long time) { List startTimes = new ArrayList(m_reports.keySet()); @@ -84,12 +75,6 @@ public void cleanup(long time) { } public void destory() { - super.release(this); - } - - @Override - public void enableLogging(Logger logger) { - m_logger = logger; } @Override @@ -188,7 +173,7 @@ public Map loadHourlyReports(long startTime, StoragePolicy policy, in } catch (Throwable e) { t.setStatus(e); Cat.logError(e); - m_logger.error(String.format("Error when loading %s reports of %s!", m_name, new Date(startTime)), e); + LOGGER.error("Error when loading {} reports of {}.", m_name, new Date(startTime), e); } finally { t.complete(); @@ -238,11 +223,11 @@ public void setName(String name) { m_name = name; } - public void setReportContentDao(HourlyReportContentDao reportContentDao) { + public void setReportContentDao(HourlyReportContentRepository reportContentDao) { m_reportContentDao = reportContentDao; } - public void setReportDao(HourlyReportDao reportDao) { + public void setReportDao(HourlyReportRepository reportDao) { m_reportDao = reportDao; } @@ -256,6 +241,7 @@ public void setValidator(DomainValidator validator) { private void storeDatabase(long startTime, Map reports) { Date period = new Date(startTime); + Date creationDate = new Date(); String ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress(); for (T report : reports.values()) { @@ -268,16 +254,18 @@ private void storeDatabase(long startTime, Map reports) { r.setPeriod(period); r.setIp(ip); r.setType(1); + r.setCreationDate(creationDate); m_reportDao.insert(r); - int id = r.getId(); + long id = r.getId(); byte[] binaryContent = m_reportDelegate.buildBinary(report); HourlyReportContent content = m_reportContentDao.createLocal(); content.setReportId(id); content.setContent(binaryContent); content.setPeriod(period); + content.setCreationDate(creationDate); m_reportContentDao.insert(content); m_reportDelegate.createHourlyTask(report); } catch (Throwable e) { @@ -320,7 +308,7 @@ public void storeHourlyReports(long startTime, StoragePolicy policy, int index) reports.remove(domain); } if (!errorDomains.isEmpty()) { - m_logger.info("error domain:" + errorDomains); + LOGGER.info("error domain:{}", errorDomains); } m_reportDelegate.beforeSave(reports); @@ -343,7 +331,7 @@ public void storeHourlyReports(long startTime, StoragePolicy policy, int index) } catch (Throwable e) { Cat.logError(e); t.setStatus(e); - m_logger.error(String.format("Error when storing %s reports of %s!", m_name, new Date(startTime)), e); + LOGGER.error("Error when storing {} reports of {}.", m_name, new Date(startTime), e); } finally { cleanup(startTime); t.complete(); diff --git a/cat-core/src/main/java/com/dianping/cat/report/DomainValidator.java b/cat-core/src/main/java/com/dianping/cat/report/DomainValidator.java index 580e8d9144..48718e73f5 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/DomainValidator.java +++ b/cat-core/src/main/java/com/dianping/cat/report/DomainValidator.java @@ -18,11 +18,8 @@ */ package com.dianping.cat.report; -import org.unidal.lookup.annotation.Named; - import java.util.concurrent.ConcurrentHashMap; -@Named public class DomainValidator { private ConcurrentHashMap m_valids = new ConcurrentHashMap(); diff --git a/cat-core/src/main/java/com/dianping/cat/report/HourlyReportContentTableProvider.java b/cat-core/src/main/java/com/dianping/cat/report/HourlyReportContentTableProvider.java deleted file mode 100644 index 4cef3b0464..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/report/HourlyReportContentTableProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.report; - -import java.util.Map; - -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.mapping.TableProvider; -import org.unidal.lookup.annotation.Named; - -@Named(type = TableProvider.class, value = HourlyReportContentTableProvider.LOGIC_TABLE_NAME) -public class HourlyReportContentTableProvider implements TableProvider, Initializable { - - public final static String LOGIC_TABLE_NAME = "report-content"; - - protected String m_logicalTableName = LOGIC_TABLE_NAME; - - @Override - public String getDataSourceName(Map hints, String logicalTableName) { - return "cat"; - } - - @Override - public String getPhysicalTableName(Map hints, String logicalTableName) { - return "hourly_report_content"; - } - - @Override - public void initialize() throws InitializationException { - } - - public void setLogicalTableName(String logicalTableName) { - m_logicalTableName = logicalTableName; - } - -} \ No newline at end of file diff --git a/cat-core/src/main/java/com/dianping/cat/report/HourlyReportTableProvider.java b/cat-core/src/main/java/com/dianping/cat/report/HourlyReportTableProvider.java deleted file mode 100644 index abc67543c4..0000000000 --- a/cat-core/src/main/java/com/dianping/cat/report/HourlyReportTableProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.dianping.cat.report; - -import java.util.Map; - -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.mapping.TableProvider; -import org.unidal.lookup.annotation.Named; - -@Named(type = TableProvider.class, value = HourlyReportTableProvider.LOGIC_TABLE_NAME) -public class HourlyReportTableProvider implements TableProvider, Initializable { - - public final static String LOGIC_TABLE_NAME = "report"; - - protected String m_logicalTableName = LOGIC_TABLE_NAME; - - private String m_dataSourceName = "cat"; - - @Override - public String getDataSourceName(Map hints, String logicalTableName) { - return m_dataSourceName; - } - - @Override - public void initialize() throws InitializationException { - } - - public void setLogicalTableName(String logicalTableName) { - m_logicalTableName = logicalTableName; - } - - @Override - public String getPhysicalTableName(Map hints, String logicalTableName) { - return "hourlyreport"; - } - -} \ No newline at end of file diff --git a/cat-core/src/main/java/com/dianping/cat/report/LocalReportBucket.java b/cat-core/src/main/java/com/dianping/cat/report/LocalReportBucket.java index b022b7efb6..f43ae40649 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/LocalReportBucket.java +++ b/cat-core/src/main/java/com/dianping/cat/report/LocalReportBucket.java @@ -33,23 +33,17 @@ import java.util.Map; import java.util.concurrent.locks.ReentrantLock; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.helper.Splitters; -import org.unidal.helper.Splitters.StringSplitter; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.PathBuilder; -@Named(type = ReportBucket.class, instantiationStrategy = Named.PER_LOOKUP) -public class LocalReportBucket implements ReportBucket, LogEnabled { - @Inject +public class LocalReportBucket implements ReportBucket { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(LocalReportBucket.class); + private PathBuilder m_pathBuilder; - @Inject private ServerConfigManager m_configManager; private File m_baseDir = new File("target/bucket/report"); @@ -72,8 +66,6 @@ public class LocalReportBucket implements ReportBucket, LogEnabled { private OutputStream m_writeIndexFile; - private Logger m_logger; - private String m_logicalPath; @Override @@ -91,11 +83,6 @@ public void close() throws IOException { } } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public String findById(String id) throws IOException { Long offset = m_idToOffsets.get(id); @@ -113,7 +100,7 @@ public String findById(String id) throws IOException { return new String(bytes, "utf-8"); } catch (Exception e) { - m_logger.error(String.format("Error when reading file(%s)!", m_readDataFile), e); + SLF4J_LOGGER.error("Error when reading report bucket file, file={}.", m_readDataFile, e); } finally { m_readLock.unlock(); } @@ -147,6 +134,14 @@ public String getLogicalPath() { return m_logicalPath; } + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + + public void setPathBuilder(PathBuilder pathBuilder) { + m_pathBuilder = pathBuilder; + } + @Override public void initialize(String name, Date timestamp, int index) throws IOException { m_baseDir = new File(Cat.getCatHome(), "bucket/report"); @@ -180,7 +175,6 @@ protected void loadIndexes(File indexFile) throws IOException { m_writeLock.lock(); try { reader = new BufferedReader(new FileReader(indexFile)); - StringSplitter splitter = Splitters.by('\t'); while (true) { String line = reader.readLine(); @@ -189,11 +183,11 @@ protected void loadIndexes(File indexFile) throws IOException { break; } - List parts = splitter.split(line); + String[] parts = line.split("\t"); - if (parts.size() >= 2) { - String id = parts.remove(0); - String offset = parts.remove(0); + if (parts.length >= 2) { + String id = parts[0]; + String offset = parts[1]; try { m_idToOffsets.put(id, Long.parseLong(offset)); diff --git a/cat-core/src/main/java/com/dianping/cat/report/ReportBucketFactory.java b/cat-core/src/main/java/com/dianping/cat/report/ReportBucketFactory.java new file mode 100644 index 0000000000..1a244fc6a8 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/report/ReportBucketFactory.java @@ -0,0 +1,9 @@ +package com.dianping.cat.report; + +import java.io.IOException; +import java.util.Date; + +public interface ReportBucketFactory { + + public ReportBucket createReportBucket(String name, Date timestamp, int index) throws IOException; +} diff --git a/cat-core/src/main/java/com/dianping/cat/report/server/RemoteServersManager.java b/cat-core/src/main/java/com/dianping/cat/report/server/RemoteServersManager.java index 6cc6109073..efc1b4d47a 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/server/RemoteServersManager.java +++ b/cat-core/src/main/java/com/dianping/cat/report/server/RemoteServersManager.java @@ -22,11 +22,8 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.report.service.ModelPeriod; -@Named public class RemoteServersManager { private volatile Map> m_currentServers = new ConcurrentHashMap>(); diff --git a/cat-core/src/main/java/com/dianping/cat/report/server/ServersUpdaterManager.java b/cat-core/src/main/java/com/dianping/cat/report/server/ServersUpdaterManager.java index fe9ca1f3c1..c8346d44fd 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/server/ServersUpdaterManager.java +++ b/cat-core/src/main/java/com/dianping/cat/report/server/ServersUpdaterManager.java @@ -22,27 +22,28 @@ import java.util.Map; import java.util.Set; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.task.TimerSyncTask; import com.dianping.cat.task.TimerSyncTask.SyncHandler; -@Named -public class ServersUpdaterManager implements Initializable { +public class ServersUpdaterManager { + private static final Logger LOGGER = LoggerFactory.getLogger(ServersUpdaterManager.class); - @Inject private ServersUpdater m_remoteServerUpdater; - @Inject private RemoteServersManager m_remoteServersManager; - @Override - public void initialize() throws InitializationException { + private volatile boolean m_initialized; + + public synchronized void initialize() { + if (m_initialized) { + return; + } + TimerSyncTask.getInstance().register(new SyncHandler() { @Override @@ -63,9 +64,19 @@ public void handle() throws Exception { m_remoteServersManager.setLastServers(lastServers); } catch (Exception e) { + LOGGER.error("Unable to update remote server cache.", e); Cat.logError(e); } } }); + m_initialized = true; + } + + public void setRemoteServerUpdater(ServersUpdater remoteServerUpdater) { + m_remoteServerUpdater = remoteServerUpdater; + } + + public void setRemoteServersManager(RemoteServersManager remoteServersManager) { + m_remoteServersManager = remoteServersManager; } } diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/AbstractReportService.java b/cat-core/src/main/java/com/dianping/cat/report/service/AbstractReportService.java index 5dcf87f61c..263b9e4411 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/service/AbstractReportService.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/AbstractReportService.java @@ -28,36 +28,29 @@ import java.util.Map.Entry; import java.util.Set; -import org.codehaus.plexus.logging.LogEnabled; -import org.codehaus.plexus.logging.Logger; -import org.unidal.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.lookup.annotation.Inject; +import org.springframework.dao.EmptyResultDataAccessException; import com.dianping.cat.Cat; import com.dianping.cat.core.dal.DailyReport; import com.dianping.cat.core.dal.DailyReportContent; -import com.dianping.cat.core.dal.DailyReportContentDao; -import com.dianping.cat.core.dal.DailyReportDao; +import com.dianping.cat.mybatis.DailyReportContentRepository; import com.dianping.cat.core.dal.HourlyReport; import com.dianping.cat.core.dal.HourlyReportContent; -import com.dianping.cat.core.dal.HourlyReportContentDao; -import com.dianping.cat.core.dal.HourlyReportDao; -import com.dianping.cat.core.dal.HourlyReportEntity; +import com.dianping.cat.mybatis.HourlyReportContentRepository; +import com.dianping.cat.mybatis.HourlyReportRepository; import com.dianping.cat.core.dal.MonthlyReport; import com.dianping.cat.core.dal.MonthlyReportContent; -import com.dianping.cat.core.dal.MonthlyReportContentDao; -import com.dianping.cat.core.dal.MonthlyReportDao; -import com.dianping.cat.core.dal.MonthlyReportEntity; +import com.dianping.cat.mybatis.MonthlyReportContentRepository; +import com.dianping.cat.mybatis.MonthlyReportRepository; import com.dianping.cat.core.dal.WeeklyReport; import com.dianping.cat.core.dal.WeeklyReportContent; -import com.dianping.cat.core.dal.WeeklyReportContentDao; -import com.dianping.cat.core.dal.WeeklyReportDao; -import com.dianping.cat.core.dal.WeeklyReportEntity; +import com.dianping.cat.mybatis.WeeklyReportContentRepository; +import com.dianping.cat.mybatis.WeeklyReportRepository; +import com.dianping.cat.mybatis.DailyReportRepository; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.message.Event; -public abstract class AbstractReportService implements LogEnabled, ReportService { +public abstract class AbstractReportService implements ReportService { public static final int s_hourly = 1; @@ -69,31 +62,21 @@ public abstract class AbstractReportService implements LogEnabled, ReportServ public static final int s_customer = 5; - @Inject - protected HourlyReportDao m_hourlyReportDao; + protected HourlyReportRepository m_hourlyReportDao; - @Inject - protected HourlyReportContentDao m_hourlyReportContentDao; + protected HourlyReportContentRepository m_hourlyReportContentDao; - @Inject - protected DailyReportDao m_dailyReportDao; + protected DailyReportRepository m_dailyReportDao; - @Inject - protected DailyReportContentDao m_dailyReportContentDao; + protected DailyReportContentRepository m_dailyReportContentDao; - @Inject - protected WeeklyReportDao m_weeklyReportDao; + protected WeeklyReportRepository m_weeklyReportDao; - @Inject - protected WeeklyReportContentDao m_weeklyReportContentDao; + protected WeeklyReportContentRepository m_weeklyReportContentDao; - @Inject - protected MonthlyReportDao m_monthlyReportDao; + protected MonthlyReportRepository m_monthlyReportDao; - @Inject - protected MonthlyReportContentDao m_monthlyReportContentDao; - - protected Logger m_logger; + protected MonthlyReportContentRepository m_monthlyReportContentDao; private Map> m_domains = new LinkedHashMap>() { @@ -129,24 +112,20 @@ public int computeQueryType(Date start, Date end) { return s_customer; } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } - @Override public boolean insertDailyReport(DailyReport report, byte[] content) { + ensureReportRepositories(); try { m_dailyReportDao.insert(report); - int id = report.getId(); + long id = report.getId(); DailyReportContent proto = m_dailyReportContentDao.createLocal(); proto.setReportId(id); proto.setContent(content); m_dailyReportContentDao.insert(proto); return true; - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); return false; } @@ -154,10 +133,11 @@ public boolean insertDailyReport(DailyReport report, byte[] content) { @Override public boolean insertHourlyReport(HourlyReport report, byte[] content) { + ensureReportRepositories(); try { m_hourlyReportDao.insert(report); - int id = report.getId(); + long id = report.getId(); HourlyReportContent proto = m_hourlyReportContentDao.createLocal(); proto.setReportId(id); @@ -165,7 +145,7 @@ public boolean insertHourlyReport(HourlyReport report, byte[] content) { proto.setPeriod(report.getPeriod()); m_hourlyReportContentDao.insert(proto); return true; - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); return false; } @@ -173,10 +153,10 @@ public boolean insertHourlyReport(HourlyReport report, byte[] content) { @Override public boolean insertMonthlyReport(MonthlyReport report, byte[] content) { + ensureReportRepositories(); try { MonthlyReport monthReport = m_monthlyReportDao - .findReportByDomainNamePeriod(report.getPeriod(), report.getDomain(), report.getName(), - MonthlyReportEntity.READSET_FULL); + .findReportByDomainNamePeriod(report.getPeriod(), report.getDomain(), report.getName()); if (monthReport != null) { MonthlyReportContent reportContent = m_monthlyReportContentDao.createLocal(); @@ -186,7 +166,7 @@ public boolean insertMonthlyReport(MonthlyReport report, byte[] content) { m_monthlyReportDao.deleteReportByDomainNamePeriod(report); m_monthlyReportContentDao.deleteByPK(reportContent); } - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { } catch (Exception e) { Cat.logError(e); } @@ -194,7 +174,7 @@ public boolean insertMonthlyReport(MonthlyReport report, byte[] content) { try { m_monthlyReportDao.insert(report); - int id = report.getId(); + long id = report.getId(); MonthlyReportContent proto = m_monthlyReportContentDao.createLocal(); proto.setReportId(id); @@ -202,7 +182,7 @@ public boolean insertMonthlyReport(MonthlyReport report, byte[] content) { m_monthlyReportContentDao.insert(proto); return true; - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); return false; } @@ -210,10 +190,10 @@ public boolean insertMonthlyReport(MonthlyReport report, byte[] content) { @Override public boolean insertWeeklyReport(WeeklyReport report, byte[] content) { + ensureReportRepositories(); try { WeeklyReport weeklyReport = m_weeklyReportDao - .findReportByDomainNamePeriod(report.getPeriod(), report.getDomain(), report.getName(), - WeeklyReportEntity.READSET_FULL); + .findReportByDomainNamePeriod(report.getPeriod(), report.getDomain(), report.getName()); if (weeklyReport != null) { WeeklyReportContent reportContent = m_weeklyReportContentDao.createLocal(); @@ -223,7 +203,7 @@ public boolean insertWeeklyReport(WeeklyReport report, byte[] content) { m_weeklyReportContentDao.deleteByPK(reportContent); m_weeklyReportDao.deleteReportByDomainNamePeriod(report); } - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { } catch (Exception e) { Cat.logError(e); } @@ -231,14 +211,14 @@ public boolean insertWeeklyReport(WeeklyReport report, byte[] content) { try { m_weeklyReportDao.insert(report); - int id = report.getId(); + long id = report.getId(); WeeklyReportContent proto = m_weeklyReportContentDao.createLocal(); proto.setReportId(id); proto.setContent(content); m_weeklyReportContentDao.insert(proto); return true; - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); return false; } @@ -247,6 +227,7 @@ public boolean insertWeeklyReport(WeeklyReport report, byte[] content) { public abstract T makeReport(String domain, Date start, Date end); public Set queryAllDomainNames(Date start, Date end, String name) { + ensureReportRepositories(); Set domains = new HashSet(); long startTime = start.getTime(); long endTime = end.getTime(); @@ -265,7 +246,7 @@ private Set queryAllDomains(Date date, String name) { domains = new HashSet(); try { List reports = m_hourlyReportDao - .findAllByPeriodName(date, name, HourlyReportEntity.READSET_DOMAIN_NAME); + .findAllByPeriodName(date, name); if (reports != null) { for (HourlyReport report : reports) { @@ -274,7 +255,7 @@ private Set queryAllDomains(Date date, String name) { } Cat.logEvent("FindDomain", key, Event.SUCCESS, domains.toString()); m_domains.put(key, domains); - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); } } @@ -291,6 +272,7 @@ private Set queryAllDomains(Date date, String name) { public abstract T queryMonthlyReport(String domain, Date start); public T queryReport(String domain, Date start, Date end) { + ensureReportRepositories(); int type = computeQueryType(start, end); T report = null; @@ -314,4 +296,45 @@ public T queryReport(String domain, Date start, Date end) { @Override public abstract T queryWeeklyReport(String domain, Date start); + protected void ensureReportRepositories() { + if (m_hourlyReportDao == null || m_hourlyReportContentDao == null || m_dailyReportDao == null + || m_dailyReportContentDao == null || m_weeklyReportDao == null + || m_weeklyReportContentDao == null || m_monthlyReportDao == null + || m_monthlyReportContentDao == null) { + throw new IllegalStateException("Report repositories are required for " + getClass().getSimpleName() + "."); + } + } + + public void setDailyReportContentDao(DailyReportContentRepository dailyReportContentDao) { + m_dailyReportContentDao = dailyReportContentDao; + } + + public void setDailyReportDao(DailyReportRepository dailyReportDao) { + m_dailyReportDao = dailyReportDao; + } + + public void setHourlyReportContentDao(HourlyReportContentRepository hourlyReportContentDao) { + m_hourlyReportContentDao = hourlyReportContentDao; + } + + public void setHourlyReportDao(HourlyReportRepository hourlyReportDao) { + m_hourlyReportDao = hourlyReportDao; + } + + public void setMonthlyReportContentDao(MonthlyReportContentRepository monthlyReportContentDao) { + m_monthlyReportContentDao = monthlyReportContentDao; + } + + public void setMonthlyReportDao(MonthlyReportRepository monthlyReportDao) { + m_monthlyReportDao = monthlyReportDao; + } + + public void setWeeklyReportContentDao(WeeklyReportContentRepository weeklyReportContentDao) { + m_weeklyReportContentDao = weeklyReportContentDao; + } + + public void setWeeklyReportDao(WeeklyReportRepository weeklyReportDao) { + m_weeklyReportDao = weeklyReportDao; + } + } diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/BaseCompositeModelService.java b/cat-core/src/main/java/com/dianping/cat/report/service/BaseCompositeModelService.java index 8154926b8d..fa0cf98833 100755 --- a/cat-core/src/main/java/com/dianping/cat/report/service/BaseCompositeModelService.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/BaseCompositeModelService.java @@ -24,11 +24,6 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.helper.Splitters; -import org.unidal.lookup.annotation.Inject; - import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.configuration.NetworkInterfaceManager; @@ -38,21 +33,20 @@ import com.dianping.cat.report.server.RemoteServersManager; public abstract class BaseCompositeModelService extends ModelServiceWithCalSupport - implements ModelService, Initializable { + implements ModelService { - @Inject protected ServerConfigManager m_configManager; - @Inject private RemoteServersManager m_serverManager; - @Inject private List> m_services; private List> m_allServices = new ArrayList>(); private String m_name; + private volatile boolean m_initialized; + public BaseCompositeModelService(String name) { m_name = name; } @@ -64,12 +58,31 @@ public String getName() { return m_name; } - @Override - public void initialize() throws InitializationException { - m_allServices.addAll(m_services); + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + + if (m_configManager == null) { + throw new IllegalStateException("ServerConfigManager is required for " + getClass().getSimpleName() + "."); + } + if (m_serverManager == null) { + throw new IllegalStateException("RemoteServersManager is required for " + getClass().getSimpleName() + "."); + } + m_allServices.clear(); + + if (m_services != null) { + m_allServices.addAll(m_services); + } String remoteServers = m_configManager.getConsoleRemoteServers(); - List endpoints = Splitters.by(',').noEmptyItem().trim().split(remoteServers); + List endpoints = splitEndpoints(remoteServers); for (String endpoint : endpoints) { int pos = endpoint.indexOf(':'); @@ -83,6 +96,7 @@ public void initialize() throws InitializationException { remote.setRemoteServersManager(m_serverManager); m_allServices.add(remote); } + m_initialized = true; } private String buildHost(String endpoint, int pos) { @@ -94,8 +108,26 @@ private String buildHost(String endpoint, int pos) { return host; } + private List splitEndpoints(String remoteServers) { + List endpoints = new ArrayList(); + + if (remoteServers != null) { + for (String endpoint : remoteServers.split(",")) { + String value = endpoint.trim(); + + if (value.length() > 0) { + endpoints.add(value); + } + } + } + + return endpoints; + } + @Override public ModelResponse invoke(final ModelRequest request) { + ensureInitialized(); + int requireSize = 0; final List> responses = Collections.synchronizedList(new ArrayList>()); final Semaphore semaphore = new Semaphore(0); @@ -167,6 +199,8 @@ public void run() { @Override public boolean isEligable(ModelRequest request) { + ensureInitialized(); + for (ModelService service : m_allServices) { if (service.isEligable(request)) { return true; @@ -188,4 +222,16 @@ public String toString() { return sb.toString(); } + + public void setServices(List> services) { + m_services = services; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + + public void setServerManager(RemoteServersManager serverManager) { + m_serverManager = serverManager; + } } diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/BaseHistoricalModelService.java b/cat-core/src/main/java/com/dianping/cat/report/service/BaseHistoricalModelService.java index 229412e10a..e290f909e2 100755 --- a/cat-core/src/main/java/com/dianping/cat/report/service/BaseHistoricalModelService.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/BaseHistoricalModelService.java @@ -18,24 +18,21 @@ */ package com.dianping.cat.report.service; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.annotation.Inject; - import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; public abstract class BaseHistoricalModelService extends ModelServiceWithCalSupport - implements ModelService, Initializable { + implements ModelService { - @Inject protected ServerConfigManager m_configManager; private boolean m_localMode = true; private String m_name; + private volatile boolean m_initialized; + public BaseHistoricalModelService(String name) { m_name = name; } @@ -47,13 +44,28 @@ public String getName() { return m_name; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + + if (m_configManager == null) { + throw new IllegalStateException("ServerConfigManager is required for " + getClass().getSimpleName() + "."); + } m_localMode = m_configManager.isLocalMode(); + m_initialized = true; } @Override public ModelResponse invoke(ModelRequest request) { + ensureInitialized(); + ModelResponse response = new ModelResponse(); Transaction t = newTransaction("ModelService", getClass().getSimpleName()); t.addData("thread", Thread.currentThread()); @@ -76,6 +88,8 @@ public ModelResponse invoke(ModelRequest request) { @Override public boolean isEligable(ModelRequest request) { + ensureInitialized(); + return request.getPeriod().isHistorical(); } @@ -83,6 +97,10 @@ protected boolean isLocalMode() { return m_localMode; } + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(64); diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/BaseRemoteModelService.java b/cat-core/src/main/java/com/dianping/cat/report/service/BaseRemoteModelService.java index ab5b2bbe6b..5cd1e2ba84 100755 --- a/cat-core/src/main/java/com/dianping/cat/report/service/BaseRemoteModelService.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/BaseRemoteModelService.java @@ -23,16 +23,15 @@ import com.dianping.cat.message.Message; import com.dianping.cat.message.Transaction; import com.dianping.cat.report.server.RemoteServersManager; -import org.unidal.helper.Files; -import org.unidal.helper.Urls; -import org.unidal.lookup.annotation.Inject; import org.xml.sax.SAXException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; import java.util.Map.Entry; import java.util.Set; import java.util.zip.GZIPInputStream; @@ -49,7 +48,6 @@ public abstract class BaseRemoteModelService extends ModelServiceWithCalSuppo private int m_port = 2281; // default admin port - @Inject private String m_serviceUri = "/cat/r/model"; public BaseRemoteModelService(String name) { @@ -91,8 +89,7 @@ public ModelResponse invoke(ModelRequest request) { t.addData(url.toString()); - InputStream in = Urls.forIO().connectTimeout(1000).readTimeout(10000).withGzip().openStream(url.toExternalForm()); - String xml = Files.forIO().readFrom(in, "utf-8"); + String xml = readUrl(url); int len = xml == null ? 0 : xml.length(); @@ -138,6 +135,19 @@ public boolean isEligable(ModelRequest request) { public abstract boolean isServersFixed(); + private String readUrl(URL url) throws IOException { + URLConnection connection = url.openConnection(); + + connection.setConnectTimeout(1000); + connection.setReadTimeout(10000); + connection.setRequestProperty("Accept-Encoding", "gzip"); + + try (InputStream raw = connection.getInputStream(); + InputStream in = "gzip".equalsIgnoreCase(connection.getContentEncoding()) ? new GZIPInputStream(raw) : raw) { + return new String(in.readAllBytes(), StandardCharsets.UTF_8); + } + } + public void setHost(String host) { m_host = host; } diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/LocalModelService.java b/cat-core/src/main/java/com/dianping/cat/report/service/LocalModelService.java index c294ea99c0..61d901dd9d 100755 --- a/cat-core/src/main/java/com/dianping/cat/report/service/LocalModelService.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/LocalModelService.java @@ -22,9 +22,8 @@ import java.util.ConcurrentModificationException; import java.util.List; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.annotation.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Constants; import com.dianping.cat.analysis.AbstractMessageAnalyzer; @@ -33,14 +32,13 @@ import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.mvc.ApiPayload; -public abstract class LocalModelService implements Initializable { +public abstract class LocalModelService { + private static final Logger LOGGER = LoggerFactory.getLogger(LocalModelService.class); public static final int DEFAULT_SIZE = 32 * 1024; - @Inject protected ServerConfigManager m_configManager; - @Inject private MessageConsumer m_consumer; private int m_analyzerCount = 2; @@ -49,6 +47,8 @@ public abstract class LocalModelService implements Initializable { private String m_name; + private volatile boolean m_initialized; + public LocalModelService(String name) { m_name = name; } @@ -66,12 +66,19 @@ public String getName() { @SuppressWarnings("unchecked") protected List getReport(ModelPeriod period, String domain) throws Exception { + ensureInitialized(); + List analyzers = null; if (domain == null || domain.length() == 0) { domain = m_defaultDomain; } + if (m_consumer == null) { + LOGGER.warn("Message consumer is not configured for local model service, service={}, period={}, domain={}.", + m_name, period, domain); + return null; + } if (period.isCurrent()) { analyzers = m_consumer.getCurrentAnalyzer(m_name); } else if (period.isLast()) { @@ -91,6 +98,8 @@ protected List getReport(ModelPeriod period, String domain) throws Exception } public String getReport(ModelRequest request, ModelPeriod period, String domain, ApiPayload payload) throws Exception { + ensureInitialized(); + try { return buildReport(request, period, domain, payload); } catch (ConcurrentModificationException e) { @@ -98,10 +107,34 @@ public String getReport(ModelRequest request, ModelPeriod period, String domain, } } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + + if (m_configManager == null) { + throw new IllegalStateException("ServerConfigManager is required for " + getClass().getSimpleName() + "."); + } + if (m_consumer == null) { + throw new IllegalStateException("MessageConsumer is required for " + getClass().getSimpleName() + "."); + } m_defaultDomain = m_configManager.getConsoleDefaultDomain(); m_analyzerCount = m_configManager.getThreadsOfRealtimeAnalyzer(m_name); + m_initialized = true; + } + + public void setConfigManager(ServerConfigManager configManager) { + m_configManager = configManager; + } + + public void setConsumer(MessageConsumer consumer) { + m_consumer = consumer; } public boolean isEligable(ModelRequest request) { diff --git a/cat-core/src/main/java/com/dianping/cat/report/service/ModelServiceWithCalSupport.java b/cat-core/src/main/java/com/dianping/cat/report/service/ModelServiceWithCalSupport.java index baa9448122..54dd043c76 100644 --- a/cat-core/src/main/java/com/dianping/cat/report/service/ModelServiceWithCalSupport.java +++ b/cat-core/src/main/java/com/dianping/cat/report/service/ModelServiceWithCalSupport.java @@ -21,13 +21,11 @@ import java.io.PrintWriter; import java.io.StringWriter; -import org.unidal.lookup.ContainerHolder; - import com.dianping.cat.Cat; import com.dianping.cat.message.Transaction; import com.dianping.cat.message.internal.DefaultEvent; -public abstract class ModelServiceWithCalSupport extends ContainerHolder { +public abstract class ModelServiceWithCalSupport { private Transaction m_current; protected void logError(Throwable cause) { diff --git a/cat-core/src/main/java/com/dianping/cat/sample/BaseEntity.java b/cat-core/src/main/java/com/dianping/cat/sample/BaseEntity.java new file mode 100644 index 0000000000..eb7388d83e --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/BaseEntity.java @@ -0,0 +1,42 @@ +package com.dianping.cat.sample; + +import java.util.Formattable; +import java.util.Formatter; + +import com.dianping.cat.sample.transform.DefaultXmlBuilder; + +public abstract class BaseEntity implements IEntity, Formattable { + + public static final String XML = "%.3s"; + + public static final String XML_COMPACT = "%s"; + + protected void assertAttributeEquals(Object instance, String entityName, String name, Object expectedValue, Object actualValue) { + if (expectedValue == null && actualValue != null || expectedValue != null && !expectedValue.equals(actualValue)) { + throw new IllegalArgumentException(String.format("Mismatched entity(%s) found! Same %s attribute is expected! %s: %s.", entityName, name, entityName, instance)); + } + } + + protected boolean equals(Object o1, Object o2) { + if (o1 == null) { + return o2 == null; + } else if (o2 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + boolean compact = (precision == 0); + DefaultXmlBuilder builder = new DefaultXmlBuilder(compact); + + formatter.format("%s", builder.buildXml(this)); + } + + @Override + public String toString() { + return new DefaultXmlBuilder().buildXml(this); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/Constants.java b/cat-core/src/main/java/com/dianping/cat/sample/Constants.java new file mode 100644 index 0000000000..1ce7ea5c0b --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/Constants.java @@ -0,0 +1,14 @@ +package com.dianping.cat.sample; + +public class Constants { + + public static final String ATTR_ID = "id"; + + public static final String ATTR_SAMPLE = "sample"; + + public static final String ENTITY_DOMAIN = "domain"; + + public static final String ENTITY_DOMAINS = "domains"; + + public static final String ENTITY_SAMPLE_CONFIG = "sample-config"; +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/IEntity.java b/cat-core/src/main/java/com/dianping/cat/sample/IEntity.java new file mode 100644 index 0000000000..8be775379f --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/IEntity.java @@ -0,0 +1,8 @@ +package com.dianping.cat.sample; + +public interface IEntity { + public void accept(IVisitor visitor); + + public void mergeAttributes(T other); + +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/IVisitor.java b/cat-core/src/main/java/com/dianping/cat/sample/IVisitor.java new file mode 100644 index 0000000000..d28d841abe --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/IVisitor.java @@ -0,0 +1,11 @@ +package com.dianping.cat.sample; + +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public interface IVisitor { + + public void visitDomain(Domain domain); + + public void visitSampleConfig(SampleConfig sampleConfig); +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/entity/Domain.java b/cat-core/src/main/java/com/dianping/cat/sample/entity/Domain.java new file mode 100644 index 0000000000..76cc01e63d --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/entity/Domain.java @@ -0,0 +1,77 @@ +package com.dianping.cat.sample.entity; + +import static com.dianping.cat.sample.Constants.ATTR_ID; +import static com.dianping.cat.sample.Constants.ENTITY_DOMAIN; + +import com.dianping.cat.sample.BaseEntity; +import com.dianping.cat.sample.IVisitor; + +public class Domain extends BaseEntity { + private String m_id; + + private Double m_sample; + + public Domain() { + } + + public Domain(String id) { + m_id = id; + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitDomain(this); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Domain) { + Domain _o = (Domain) obj; + + if (!equals(getId(), _o.getId())) { + return false; + } + + return true; + } + + return false; + } + + public String getId() { + return m_id; + } + + public Double getSample() { + return m_sample; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_id == null ? 0 : m_id.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(Domain other) { + assertAttributeEquals(other, ENTITY_DOMAIN, ATTR_ID, m_id, other.getId()); + + if (other.getSample() != null) { + m_sample = other.getSample(); + } + } + + public Domain setId(String id) { + m_id = id; + return this; + } + + public Domain setSample(Double sample) { + m_sample = sample; + return this; + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/entity/SampleConfig.java b/cat-core/src/main/java/com/dianping/cat/sample/entity/SampleConfig.java new file mode 100644 index 0000000000..4ab903b5e5 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/entity/SampleConfig.java @@ -0,0 +1,66 @@ +package com.dianping.cat.sample.entity; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.dianping.cat.sample.BaseEntity; +import com.dianping.cat.sample.IVisitor; + +public class SampleConfig extends BaseEntity { + private Map m_domains = new LinkedHashMap(); + + public SampleConfig() { + } + + @Override + public void accept(IVisitor visitor) { + visitor.visitSampleConfig(this); + } + + public SampleConfig addDomain(Domain domain) { + m_domains.put(domain.getId(), domain); + return this; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SampleConfig) { + SampleConfig _o = (SampleConfig) obj; + + if (!equals(getDomains(), _o.getDomains())) { + return false; + } + + + return true; + } + + return false; + } + + public Domain findDomain(String id) { + return m_domains.get(id); + } + + public Map getDomains() { + return m_domains; + } + + @Override + public int hashCode() { + int hash = 0; + + hash = hash * 31 + (m_domains == null ? 0 : m_domains.hashCode()); + + return hash; + } + + @Override + public void mergeAttributes(SampleConfig other) { + } + + public Domain removeDomain(String id) { + return m_domains.remove(id); + } + +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultLinker.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultLinker.java new file mode 100644 index 0000000000..7e8b00babe --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultLinker.java @@ -0,0 +1,38 @@ +package com.dianping.cat.sample.transform; + +import java.util.ArrayList; +import java.util.List; +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public class DefaultLinker implements ILinker { + private boolean m_deferrable; + + private List m_deferedJobs = new ArrayList(); + + public DefaultLinker(boolean deferrable) { + m_deferrable = deferrable; + } + + public void finish() { + for (Runnable job : m_deferedJobs) { + job.run(); + } + } + + @Override + public boolean onDomain(final SampleConfig parent, final Domain domain) { + if (m_deferrable) { + m_deferedJobs.add(new Runnable() { + @Override + public void run() { + parent.addDomain(domain); + } + }); + } else { + parent.addDomain(domain); + } + + return true; + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxMaker.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxMaker.java new file mode 100644 index 0000000000..84a8e9924d --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxMaker.java @@ -0,0 +1,59 @@ +package com.dianping.cat.sample.transform; + +import static com.dianping.cat.sample.Constants.ATTR_ID; +import static com.dianping.cat.sample.Constants.ATTR_SAMPLE; + +import org.xml.sax.Attributes; + +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public class DefaultSaxMaker implements IMaker { + + @Override + public Domain buildDomain(Attributes attributes) { + String id = attributes.getValue(ATTR_ID); + String sample = attributes.getValue(ATTR_SAMPLE); + Domain domain = new Domain(id); + + if (sample != null) { + domain.setSample(convert(Double.class, sample, null)); + } + + return domain; + } + + @Override + public SampleConfig buildSampleConfig(Attributes attributes) { + SampleConfig sampleConfig = new SampleConfig(); + + return sampleConfig; + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class || type == Boolean.TYPE) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class || type == Integer.TYPE) { + return (T) Integer.valueOf(value); + } else if (type == Long.class || type == Long.TYPE) { + return (T) Long.valueOf(value); + } else if (type == Short.class || type == Short.TYPE) { + return (T) Short.valueOf(value); + } else if (type == Float.class || type == Float.TYPE) { + return (T) Float.valueOf(value); + } else if (type == Double.class || type == Double.TYPE) { + return (T) Double.valueOf(value); + } else if (type == Byte.class || type == Byte.TYPE) { + return (T) Byte.valueOf(value); + } else if (type == Character.class || type == Character.TYPE) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxParser.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxParser.java new file mode 100644 index 0000000000..5384a70dfa --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultSaxParser.java @@ -0,0 +1,227 @@ +package com.dianping.cat.sample.transform; + +import static com.dianping.cat.sample.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.sample.Constants.ENTITY_SAMPLE_CONFIG; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import com.dianping.cat.sample.IEntity; +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public class DefaultSaxParser extends DefaultHandler { + + private DefaultLinker m_linker = new DefaultLinker(true); + + private DefaultSaxMaker m_maker = new DefaultSaxMaker(); + + private Stack m_tags = new Stack(); + + private Stack m_objs = new Stack(); + + private IEntity m_entity; + + private StringBuilder m_text = new StringBuilder(); + + public static SampleConfig parse(InputStream in) throws SAXException, IOException { + return parseEntity(SampleConfig.class, new InputSource(removeBOM(in))); + } + + public static SampleConfig parse(Reader reader) throws SAXException, IOException { + return parseEntity(SampleConfig.class, new InputSource(removeBOM(reader))); + } + + public static SampleConfig parse(String xml) throws SAXException, IOException { + return parseEntity(SampleConfig.class, new InputSource(new StringReader(removeBOM(xml)))); + } + + @SuppressWarnings("unchecked") + private static > T parseEntity(Class type, InputSource is) throws SAXException, IOException { + try { + DefaultSaxParser handler = new DefaultSaxParser(); + SAXParserFactory factory = SAXParserFactory.newInstance(); + + factory.setValidating(false); + factory.setFeature("http://xml.org/sax/features/validation", false); + + factory.newSAXParser().parse(is, handler); + return (T) handler.getEntity(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Unable to get SAX parser instance!", e); + } + } + + public static > T parseEntity(Class type, InputStream in) throws SAXException, IOException { + return parseEntity(type, new InputSource(removeBOM(in))); + } + + public static > T parseEntity(Class type, String xml) throws SAXException, IOException { + return parseEntity(type, new InputSource(new StringReader(removeBOM(xml)))); + } + + // to remove Byte Order Mark(BOM) at the head of windows utf-8 file + @SuppressWarnings("unchecked") + private static T removeBOM(T obj) throws IOException { + if (obj instanceof String) { + String str = (String) obj; + + if (str.length() != 0 && str.charAt(0) == 0xFEFF) { + return (T) str.substring(1); + } else { + return obj; + } + } else if (obj instanceof InputStream) { + BufferedInputStream in = new BufferedInputStream((InputStream) obj); + + in.mark(3); + + if (in.read() != 0xEF || in.read() != 0xBB || in.read() != 0xBF) { + in.reset(); + } + + return (T) in; + } else if (obj instanceof Reader) { + BufferedReader in = new BufferedReader((Reader) obj); + + in.mark(1); + + if (in.read() != 0xFEFF) { + in.reset(); + } + + return (T) in; + } else { + return obj; + } + } + + @SuppressWarnings("unchecked") + protected T convert(Class type, String value, T defaultValue) { + if (value == null || value.length() == 0) { + return defaultValue; + } + + if (type == Boolean.class) { + return (T) Boolean.valueOf(value); + } else if (type == Integer.class) { + return (T) Integer.valueOf(value); + } else if (type == Long.class) { + return (T) Long.valueOf(value); + } else if (type == Short.class) { + return (T) Short.valueOf(value); + } else if (type == Float.class) { + return (T) Float.valueOf(value); + } else if (type == Double.class) { + return (T) Double.valueOf(value); + } else if (type == Byte.class) { + return (T) Byte.valueOf(value); + } else if (type == Character.class) { + return (T) (Character) value.charAt(0); + } else { + return (T) value; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + m_text.append(ch, start, length); + } + + @Override + public void endDocument() throws SAXException { + m_linker.finish(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (uri == null || uri.length() == 0) { + m_objs.pop(); + m_tags.pop(); + + } + + m_text.setLength(0); + } + + private IEntity getEntity() { + return m_entity; + } + + protected String getText() { + return m_text.toString(); + } + + private void parseForDomain(Domain parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + m_objs.push(parentObj); + m_tags.push(qName); + } + + private void parseForSampleConfig(SampleConfig parentObj, String parentTag, String qName, Attributes attributes) throws SAXException { + if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_linker.onDomain(parentObj, domain); + m_objs.push(domain); + } else { + throw new SAXException(String.format("Element(%s) is not expected under sample-config!", qName)); + } + + m_tags.push(qName); + } + + private void parseRoot(String qName, Attributes attributes) throws SAXException { + if (ENTITY_SAMPLE_CONFIG.equals(qName)) { + SampleConfig sampleConfig = m_maker.buildSampleConfig(attributes); + + m_entity = sampleConfig; + m_objs.push(sampleConfig); + m_tags.push(qName); + } else if (ENTITY_DOMAIN.equals(qName)) { + Domain domain = m_maker.buildDomain(attributes); + + m_entity = domain; + m_objs.push(domain); + m_tags.push(qName); + } else { + throw new SAXException("Unknown root element(" + qName + ") found!"); + } + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (uri == null || uri.length() == 0) { + if (m_objs.isEmpty()) { // root + parseRoot(qName, attributes); + } else { + Object parent = m_objs.peek(); + String tag = m_tags.peek(); + + if (parent instanceof SampleConfig) { + parseForSampleConfig((SampleConfig) parent, tag, qName, attributes); + } else if (parent instanceof Domain) { + parseForDomain((Domain) parent, tag, qName, attributes); + } else { + throw new RuntimeException(String.format("Unknown entity(%s) under %s!", qName, parent.getClass().getName())); + } + } + + m_text.setLength(0); + } else { + throw new SAXException(String.format("Namespace(%s) is not supported by %s.", uri, this.getClass().getName())); + } + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultXmlBuilder.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultXmlBuilder.java new file mode 100644 index 0000000000..782596d8cb --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/DefaultXmlBuilder.java @@ -0,0 +1,213 @@ +package com.dianping.cat.sample.transform; + +import static com.dianping.cat.sample.Constants.ATTR_ID; +import static com.dianping.cat.sample.Constants.ATTR_SAMPLE; +import static com.dianping.cat.sample.Constants.ENTITY_DOMAIN; +import static com.dianping.cat.sample.Constants.ENTITY_SAMPLE_CONFIG; + +import java.lang.reflect.Array; +import java.util.Collection; + +import com.dianping.cat.sample.IEntity; +import com.dianping.cat.sample.IVisitor; +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public class DefaultXmlBuilder implements IVisitor { + + private IVisitor m_visitor = this; + + private int m_level; + + private StringBuilder m_sb; + + private boolean m_compact; + + public DefaultXmlBuilder() { + this(false); + } + + public DefaultXmlBuilder(boolean compact) { + this(compact, new StringBuilder(4096)); + } + + public DefaultXmlBuilder(boolean compact, StringBuilder sb) { + m_compact = compact; + m_sb = sb; + m_sb.append("\r\n"); + } + + public String buildXml(IEntity entity) { + entity.accept(m_visitor); + return m_sb.toString(); + } + + protected void endTag(String name) { + m_level--; + + indent(); + m_sb.append("\r\n"); + } + + protected String escape(Object value) { + return escape(value, false); + } + + protected String escape(Object value, boolean text) { + if (value == null) { + return null; + } + + String str = toString(value); + int len = str.length(); + StringBuilder sb = new StringBuilder(len + 16); + + for (int i = 0; i < len; i++) { + final char ch = str.charAt(i); + + switch (ch) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + case '"': + if (!text) { + sb.append("""); + break; + } + default: + sb.append(ch); + break; + } + } + + return sb.toString(); + } + + protected void indent() { + if (!m_compact) { + for (int i = m_level - 1; i >= 0; i--) { + m_sb.append(" "); + } + } + } + + protected void startTag(String name) { + startTag(name, false, null); + } + + protected void startTag(String name, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, closed, dynamicAttributes, nameValues); + } + + protected void startTag(String name, java.util.Map dynamicAttributes, Object... nameValues) { + startTag(name, null, false, dynamicAttributes, nameValues); + } + + protected void startTag(String name, Object text, boolean closed, java.util.Map dynamicAttributes, Object... nameValues) { + indent(); + + m_sb.append('<').append(name); + + int len = nameValues.length; + + for (int i = 0; i + 1 < len; i += 2) { + Object attrName = nameValues[i]; + Object attrValue = nameValues[i + 1]; + + if (attrValue != null) { + m_sb.append(' ').append(attrName).append("=\"").append(escape(attrValue)).append('"'); + } + } + + if (dynamicAttributes != null) { + for (java.util.Map.Entry e : dynamicAttributes.entrySet()) { + m_sb.append(' ').append(e.getKey()).append("=\"").append(escape(e.getValue())).append('"'); + } + } + + if (text != null && closed) { + m_sb.append('>'); + m_sb.append(escape(text, true)); + m_sb.append("\r\n"); + } else { + if (closed) { + m_sb.append('/'); + } else { + m_level++; + } + + m_sb.append(">\r\n"); + } + } + + @SuppressWarnings("unchecked") + protected String toString(Object value) { + if (value instanceof String) { + return (String) value; + } else if (value instanceof Collection) { + Collection list = (Collection) value; + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (Object item : list) { + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } else if (value.getClass().isArray()) { + int len = Array.getLength(value); + StringBuilder sb = new StringBuilder(32); + boolean first = true; + + for (int i = 0; i < len; i++) { + Object item = Array.get(value, i); + + if (first) { + first = false; + } else { + sb.append(','); + } + + if (item != null) { + sb.append(item); + } + } + + return sb.toString(); + } + + return String.valueOf(value); + } + + @Override + public void visitDomain(Domain domain) { + startTag(ENTITY_DOMAIN, true, null, ATTR_ID, domain.getId(), ATTR_SAMPLE, domain.getSample()); + } + + @Override + public void visitSampleConfig(SampleConfig sampleConfig) { + startTag(ENTITY_SAMPLE_CONFIG, null); + + if (!sampleConfig.getDomains().isEmpty()) { + for (Domain domain : sampleConfig.getDomains().values()) { + domain.accept(m_visitor); + } + } + + endTag(ENTITY_SAMPLE_CONFIG); + } +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/ILinker.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/ILinker.java new file mode 100644 index 0000000000..bb67134aff --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/ILinker.java @@ -0,0 +1,9 @@ +package com.dianping.cat.sample.transform; + +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public interface ILinker { + + public boolean onDomain(SampleConfig parent, Domain domain); +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/IMaker.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/IMaker.java new file mode 100644 index 0000000000..5d530a25c2 --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/IMaker.java @@ -0,0 +1,11 @@ +package com.dianping.cat.sample.transform; + +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public interface IMaker { + + public Domain buildDomain(T node); + + public SampleConfig buildSampleConfig(T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/sample/transform/IParser.java b/cat-core/src/main/java/com/dianping/cat/sample/transform/IParser.java new file mode 100644 index 0000000000..3523aff5ff --- /dev/null +++ b/cat-core/src/main/java/com/dianping/cat/sample/transform/IParser.java @@ -0,0 +1,10 @@ +package com.dianping.cat.sample.transform; + +import com.dianping.cat.sample.entity.Domain; +import com.dianping.cat.sample.entity.SampleConfig; + +public interface IParser { + public SampleConfig parse(IMaker maker, ILinker linker, T node); + + public void parseForDomain(IMaker maker, ILinker linker, Domain parent, T node); +} diff --git a/cat-core/src/main/java/com/dianping/cat/server/DataSourceService.java b/cat-core/src/main/java/com/dianping/cat/server/DataSourceService.java index 867f56c335..c0b52fc2c3 100644 --- a/cat-core/src/main/java/com/dianping/cat/server/DataSourceService.java +++ b/cat-core/src/main/java/com/dianping/cat/server/DataSourceService.java @@ -18,9 +18,7 @@ */ package com.dianping.cat.server; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; - -public interface DataSourceService extends Initializable { +public interface DataSourceService { public T getConnection(String category); diff --git a/cat-core/src/main/java/com/dianping/cat/server/QueryParameter.java b/cat-core/src/main/java/com/dianping/cat/server/QueryParameter.java index 65dbf4bf8d..86a3339cdf 100644 --- a/cat-core/src/main/java/com/dianping/cat/server/QueryParameter.java +++ b/cat-core/src/main/java/com/dianping/cat/server/QueryParameter.java @@ -19,11 +19,9 @@ package com.dianping.cat.server; import java.util.Date; +import java.util.LinkedList; import java.util.List; -import org.unidal.helper.Splitters; -import org.unidal.lookup.util.StringUtils; - public class QueryParameter { private String m_category; @@ -99,15 +97,29 @@ public QueryParameter setMeasurement(String measurement) { public String getSqlTags() { String tag = ""; - List tags = Splitters.by(";").noEmptyItem().split(m_tags); + List tags = splitTags(); if (!tags.isEmpty()) { - tag = StringUtils.join(tags, " AND ") + " AND "; + tag = String.join(" AND ", tags) + " AND "; } return tag; } + private List splitTags() { + List tags = new LinkedList(); + + if (m_tags != null) { + for (String item : m_tags.split(";")) { + if (item.length() > 0) { + tags.add(item); + } + } + } + + return tags; + } + public Date getStart() { return m_start; } diff --git a/cat-core/src/main/java/com/dianping/cat/service/HostinfoService.java b/cat-core/src/main/java/com/dianping/cat/service/HostinfoService.java index 21c6ac026b..959f5729c7 100644 --- a/cat-core/src/main/java/com/dianping/cat/service/HostinfoService.java +++ b/cat-core/src/main/java/com/dianping/cat/service/HostinfoService.java @@ -25,63 +25,52 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; -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.dal.jdbc.DalException; -import org.unidal.dal.jdbc.DalNotFoundException; -import org.unidal.helper.Threads; -import org.unidal.helper.Threads.Task; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; -import org.unidal.lookup.util.StringUtils; +import org.slf4j.LoggerFactory; +import org.springframework.dao.EmptyResultDataAccessException; +import com.dianping.cat.support.Threads; +import com.dianping.cat.support.Threads.Task; import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.core.dal.Hostinfo; -import com.dianping.cat.core.dal.HostinfoDao; -import com.dianping.cat.core.dal.HostinfoEntity; +import com.dianping.cat.mybatis.HostInfoRepository; import com.dianping.cat.helper.TimeHelper; -@Named(type = HostinfoService.class) -public class HostinfoService implements Initializable, LogEnabled { +public class HostinfoService { + private static final org.slf4j.Logger SLF4J_LOGGER = LoggerFactory.getLogger(HostinfoService.class); public static final String UNKNOWN_PROJECT = "UnknownProject"; - protected Logger m_logger; + private HostInfoRepository m_hostinfoDao; - @Inject - private HostinfoDao m_hostinfoDao; - - @Inject private ServerConfigManager m_manager; private Map m_ipDomains = new ConcurrentHashMap(); private Map m_hostinfos = new ConcurrentHashMap(); + private volatile boolean m_initialized; + public Hostinfo createLocal() { return m_hostinfoDao.createLocal(); } - @Override - public void enableLogging(Logger logger) { - m_logger = logger; - } + public List findAll() { + ensureInitialized(); - public List findAll() throws DalException { return new ArrayList(m_hostinfos.values()); } public Hostinfo findByIp(String ip) { + ensureInitialized(); + Hostinfo hostinfo = m_hostinfos.get(ip); if (hostinfo != null) { return hostinfo; } else { try { - hostinfo = m_hostinfoDao.findByIp(ip, HostinfoEntity.READSET_FULL); + hostinfo = m_hostinfoDao.findByIp(ip); if (hostinfo != null) { m_hostinfos.put(ip, hostinfo); @@ -89,24 +78,44 @@ public Hostinfo findByIp(String ip) { } else { return null; } - } catch (DalNotFoundException e) { + } catch (EmptyResultDataAccessException e) { + SLF4J_LOGGER.warn("Hostinfo is missing by ip={}.", ip, e); } catch (Exception e) { + SLF4J_LOGGER.error("Unable to find hostinfo by ip={}.", ip, e); Cat.logError(e); } return null; } } - @Override - public void initialize() throws InitializationException { - Threads.forGroup("Cat").start(new RefreshHost()); + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } } - private boolean insert(Hostinfo hostinfo) throws DalException { - m_hostinfos.put(hostinfo.getIp(), hostinfo); + public synchronized void initialize() { + if (m_initialized) { + return; + } + if (m_hostinfoDao == null) { + throw new IllegalStateException("HostinfoRepository is required for HostinfoService."); + } + if (m_manager == null) { + throw new IllegalStateException("ServerConfigManager is required for HostinfoService."); + } + + Threads.forGroup("Cat").start(new RefreshHost()); + m_initialized = true; + SLF4J_LOGGER.info("HostinfoService started refresh task."); + } + + private boolean insert(Hostinfo hostinfo) { int result = m_hostinfoDao.insert(hostinfo); + if (result == 1) { + m_hostinfos.put(hostinfo.getIp(), hostinfo); return true; } else { return false; @@ -114,21 +123,30 @@ private boolean insert(Hostinfo hostinfo) throws DalException { } public boolean insert(String domain, String ip) { + ensureInitialized(); + try { Hostinfo info = createLocal(); info.setDomain(domain); info.setIp(ip); - insert(info); - m_hostinfos.put(ip, info); - return true; - } catch (DalException e) { + boolean inserted = insert(info); + + if (inserted) { + SLF4J_LOGGER.info("Inserted hostinfo, domain={}, ip={}.", domain, ip); + return true; + } + SLF4J_LOGGER.warn("Hostinfo insert affected no rows, domain={}, ip={}.", domain, ip); + } catch (RuntimeException e) { + SLF4J_LOGGER.error("Unable to insert hostinfo, domain={}, ip={}.", domain, ip, e); Cat.logError(e); } return false; } public String queryDomainByIp(String ip) { + ensureInitialized(); + String project = m_ipDomains.get(ip); if (project == null) { @@ -138,6 +156,8 @@ public String queryDomainByIp(String ip) { } public String queryHostnameByIp(String ip) { + ensureInitialized(); + try { if (validateIp(ip)) { Hostinfo info = m_hostinfos.get(ip); @@ -146,7 +166,7 @@ public String queryHostnameByIp(String ip) { if (info != null) { hostname = info.getHostname(); - if (StringUtils.isNotEmpty(hostname)) { + if (isNotEmpty(hostname)) { return hostname; } } @@ -161,6 +181,7 @@ public String queryHostnameByIp(String ip) { return null; } } catch (Exception e) { + SLF4J_LOGGER.error("Unable to query hostname by ip={}.", ip, e); Cat.logError(e); } @@ -168,6 +189,8 @@ public String queryHostnameByIp(String ip) { } public List queryIpsByDomain(String domain) { + ensureInitialized(); + List ips = new ArrayList(); if (domain == null) { return ips; @@ -188,7 +211,7 @@ public List queryIpsByDomain(String domain) { protected void refresh() { try { - List hostinfos = m_hostinfoDao.findAllIp(HostinfoEntity.READSET_FULL); + List hostinfos = m_hostinfoDao.findAllIp(); Map tmpHostInfos = new ConcurrentHashMap(); Map tmpIpDomains = new ConcurrentHashMap(); @@ -198,12 +221,16 @@ protected void refresh() { } m_hostinfos = tmpHostInfos; m_ipDomains = tmpIpDomains; - } catch (DalException e) { + SLF4J_LOGGER.info("Refreshed hostinfo cache, hostCount={}.", hostinfos.size()); + } catch (RuntimeException e) { + SLF4J_LOGGER.error("Unable to refresh hostinfo cache.", e); Cat.logError("initialize HostService error", e); } } - public boolean update(int id, String domain, String ip) { + public boolean update(long id, String domain, String ip) { + ensureInitialized(); + Hostinfo info = createLocal(); info.setId(id); @@ -216,23 +243,41 @@ public boolean update(int id, String domain, String ip) { } public boolean updateHostinfo(Hostinfo hostinfo) { + ensureInitialized(); + m_hostinfos.put(hostinfo.getIp(), hostinfo); try { - m_hostinfoDao.updateByPK(hostinfo, HostinfoEntity.UPDATESET_FULL); + m_hostinfoDao.updateByPK(hostinfo); + SLF4J_LOGGER.info("Updated hostinfo, id={}, domain={}, ip={}.", hostinfo.getId(), hostinfo.getDomain(), + hostinfo.getIp()); return true; - } catch (DalException e) { + } catch (RuntimeException e) { + SLF4J_LOGGER.error("Unable to update hostinfo, id={}, domain={}, ip={}.", hostinfo.getId(), + hostinfo.getDomain(), hostinfo.getIp(), e); Cat.logError(e); return false; } } + public void setHostinfoDao(HostInfoRepository hostinfoDao) { + m_hostinfoDao = hostinfoDao; + } + + public void setServerConfigManager(ServerConfigManager manager) { + m_manager = manager; + } + private boolean validateIp(String str) { Pattern pattern = Pattern.compile( "^((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]|[*])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]|[*])$"); return pattern.matcher(str).matches(); } + private boolean isNotEmpty(String value) { + return value != null && value.length() > 0; + } + public class RefreshHost implements Task { @Override public String getName() { @@ -247,6 +292,7 @@ public void run() { try { Thread.sleep(TimeHelper.ONE_MINUTE); } catch (InterruptedException e) { + SLF4J_LOGGER.warn("Hostinfo refresh task interrupted.", e); Cat.logError(e); } } diff --git a/cat-core/src/main/java/com/dianping/cat/service/IpService.java b/cat-core/src/main/java/com/dianping/cat/service/IpService.java index 210f7da862..070a8e7cc9 100644 --- a/cat-core/src/main/java/com/dianping/cat/service/IpService.java +++ b/cat-core/src/main/java/com/dianping/cat/service/IpService.java @@ -25,14 +25,14 @@ import java.util.LinkedHashMap; import java.util.Map; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; -@Named -public class IpService implements Initializable { +public class IpService { + private static final Logger LOGGER = LoggerFactory.getLogger(IpService.class); + private static final String OTHER = "其他"; private int[] m_areaIds; @@ -55,6 +55,8 @@ public class IpService implements Initializable { private long[] m_foreignStarts; + private volatile boolean m_initialized; + private String FOREIGN_OTHER = "国外其他"; private String FOREIGN = "国外"; @@ -145,6 +147,8 @@ private IpInfo findIpInfo(long ip) { } public IpInfo findIpInfoByString(String ip) { + ensureInitialized(); + try { String[] segments = ip.split("\\."); if (segments.length != 4) { @@ -158,10 +162,17 @@ public IpInfo findIpInfoByString(String ip) { return findIpInfo(ip_num); } catch (Exception e) { + LOGGER.warn("Unable to parse ip string, ip={}.", ip, e); return null; } } + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + private void initAreaMap(InputStream areaFile) { try { BufferedReader areaReader = new BufferedReader(new InputStreamReader(areaFile)); @@ -184,6 +195,7 @@ private void initAreaMap(InputStream areaFile) { } areaReader.close(); } catch (Exception e) { + LOGGER.error("Unable to initialize China area map.", e); Cat.logError(e); } } @@ -207,6 +219,7 @@ private void initCorpMap(InputStream corpFile) { } corpReader.close(); } catch (Exception e) { + LOGGER.error("Unable to initialize China corporation map.", e); Cat.logError(e); } } @@ -233,6 +246,7 @@ private void initForeignAreaMap(InputStream areaFile) { } areaReader.close(); } catch (Exception e) { + LOGGER.error("Unable to initialize foreign area map.", e); Cat.logError(e); } } @@ -258,18 +272,25 @@ public void initForeignIpTable(InputStream ipFile) { } } catch (IOException e) { + LOGGER.error("Unable to initialize foreign ip table.", e); Cat.logError(e); } finally { try { - reader.close(); + if (reader != null) { + reader.close(); + } } catch (Exception e) { + LOGGER.warn("Unable to close foreign ip table reader.", e); Cat.logError(e); } } } - @Override - public void initialize() throws InitializationException { + public synchronized void initialize() { + if (m_initialized) { + return; + } + InputStream areaFile = IpService.class.getClassLoader().getResourceAsStream("ip/area_china"); InputStream corpFile = IpService.class.getClassLoader().getResourceAsStream("ip/corp_china"); InputStream ipFile = IpService.class.getClassLoader().getResourceAsStream("ip/iptable_china"); @@ -283,6 +304,8 @@ public void initialize() throws InitializationException { initForeignAreaMap(foreignAreaFile); initForeignIpTable(foreignIpFile); + m_initialized = true; + LOGGER.info("IpService initialized."); } public void initIpTable(InputStream ipFile) { @@ -308,11 +331,15 @@ public void initIpTable(InputStream ipFile) { } } catch (IOException e) { + LOGGER.error("Unable to initialize China ip table.", e); Cat.logError(e); } finally { try { - reader.close(); + if (reader != null) { + reader.close(); + } } catch (Exception e) { + LOGGER.warn("Unable to close China ip table reader.", e); Cat.logError(e); } } diff --git a/cat-core/src/main/java/com/dianping/cat/service/IpService2.java b/cat-core/src/main/java/com/dianping/cat/service/IpService2.java index bfebe1dea2..5e3e69ff76 100644 --- a/cat-core/src/main/java/com/dianping/cat/service/IpService2.java +++ b/cat-core/src/main/java/com/dianping/cat/service/IpService2.java @@ -25,16 +25,14 @@ import java.nio.charset.Charset; import java.util.concurrent.locks.ReentrantLock; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.helper.Files; -import org.unidal.lookup.annotation.Named; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.dianping.cat.Cat; import com.dianping.cat.service.IpService.IpInfo; -@Named -public class IpService2 implements Initializable { +public class IpService2 { + private static final Logger LOGGER = LoggerFactory.getLogger(IpService2.class); private int m_offset; @@ -46,6 +44,8 @@ public class IpService2 implements Initializable { private ReentrantLock m_lock = new ReentrantLock(); + private volatile boolean m_initialized; + private long bytesToLong(byte a, byte b, byte c, byte d) { return int2long((((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff))); } @@ -87,6 +87,8 @@ private String[] find(String ip) { } public IpInfo findIpInfoByString(String ip) { + ensureInitialized(); + String[] infos = find(ip); if (infos.length >= 7) { @@ -105,9 +107,19 @@ public IpInfo findIpInfoByString(String ip) { return null; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + load("ip/ipdata.datx"); + m_initialized = true; } private long int2long(int i) { @@ -125,9 +137,8 @@ private long ip2long(String ip) { private void load(String filename) { m_lock.lock(); - try { - InputStream is = IpService.class.getClassLoader().getResourceAsStream(filename); - m_dataBuffer = ByteBuffer.wrap(Files.forIO().readFrom(is)); + try (InputStream is = IpService.class.getClassLoader().getResourceAsStream(filename)) { + m_dataBuffer = ByteBuffer.wrap(is.readAllBytes()); m_dataBuffer.position(0); m_offset = m_dataBuffer.getInt(); // indexLength byte[] indexBytes = new byte[m_offset]; @@ -141,7 +152,8 @@ private void load(String filename) { } } m_indexBuffer.order(ByteOrder.BIG_ENDIAN); - } catch (IOException e) { + } catch (Exception e) { + LOGGER.error("Unable to load ip data, filename={}.", filename, e); Cat.logError(e); } finally { m_lock.unlock(); diff --git a/cat-core/src/main/java/com/dianping/cat/service/ProjectService.java b/cat-core/src/main/java/com/dianping/cat/service/ProjectService.java index 018bbcb7da..ed2cd60c14 100644 --- a/cat-core/src/main/java/com/dianping/cat/service/ProjectService.java +++ b/cat-core/src/main/java/com/dianping/cat/service/ProjectService.java @@ -21,27 +21,22 @@ import com.dianping.cat.Cat; import com.dianping.cat.config.server.ServerConfigManager; import com.dianping.cat.core.dal.Project; -import com.dianping.cat.core.dal.ProjectDao; -import com.dianping.cat.core.dal.ProjectEntity; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; -import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; -import org.unidal.dal.jdbc.DalException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import com.dianping.cat.mybatis.ProjectRepository; +import org.springframework.dao.EmptyResultDataAccessException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; -@Named -public class ProjectService implements Initializable { +public class ProjectService { + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectService.class); public static final String DEFAULT = "Default"; - @Inject - private ProjectDao m_projectDao; + private ProjectRepository m_projectDao; - @Inject private ServerConfigManager m_manager; private ConcurrentHashMap m_domains = new ConcurrentHashMap(); @@ -50,7 +45,11 @@ public class ProjectService implements Initializable { private ConcurrentHashMap m_cmdbToProjects = new ConcurrentHashMap(); + private volatile boolean m_initialized; + public boolean contains(String domain) { + ensureInitialized(); + return m_domains.containsKey(domain); } @@ -59,7 +58,9 @@ public Project create() { } public boolean delete(Project project) { - int id = project.getId(); + ensureInitialized(); + + long id = project.getId(); String domainName = null; for (Entry entry : m_domainToProjects.entrySet()) { @@ -87,32 +88,41 @@ public boolean delete(Project project) { return true; } catch (Exception e) { + LOGGER.error("Unable to delete project, id={}, domain={}.", id, domainName, e); Cat.logError("delete project error ", e); return false; } } - public List findAll() throws DalException { + public List findAll() { + ensureInitialized(); + return new ArrayList(m_domainToProjects.values()); } public Set findAllDomains() { + ensureInitialized(); + return m_domains.keySet(); } public Project findByDomain(String domainName) { + ensureInitialized(); + Project project = m_domainToProjects.get(domainName); if (project != null) { return project; } else { try { - Project pro = m_projectDao.findByDomain(domainName, ProjectEntity.READSET_FULL); + Project pro = m_projectDao.findByDomain(domainName); m_domainToProjects.put(pro.getDomain(), pro); return project; - } catch (DalException e) { + } catch (EmptyResultDataAccessException e) { + LOGGER.warn("Project is missing or unavailable by domain={}.", domainName, e); } catch (Exception e) { + LOGGER.error("Unable to find project by domain={}.", domainName, e); Cat.logError(e); } return null; @@ -120,6 +130,8 @@ public Project findByDomain(String domainName) { } public Map findDepartments(Collection domains) { + ensureInitialized(); + Map departments = new TreeMap(); for (String domain : domains) { @@ -147,6 +159,8 @@ public Map findDepartments(Collection domains) { } public Project findProject(String domain) { + ensureInitialized(); + Project project = m_domainToProjects.get(domain); if (project == null) { @@ -155,31 +169,60 @@ public Project findProject(String domain) { return project; } - @Override - public void initialize() throws InitializationException { + private void ensureInitialized() { + if (!m_initialized) { + initialize(); + } + } + + public synchronized void initialize() { + if (m_initialized) { + return; + } + if (!m_manager.isLocalMode()) { + LOGGER.info("Initializing ProjectService in remote mode."); refresh(); + } else { + LOGGER.info("Initializing ProjectService in local mode; skip database refresh."); } + m_initialized = true; + } + + public void setProjectDao(ProjectRepository projectDao) { + m_projectDao = projectDao; + } + + public void setServerConfigManager(ServerConfigManager manager) { + m_manager = manager; } public boolean insert(Project project) { + ensureInitialized(); + m_domainToProjects.put(project.getDomain(), project); try { int result = m_projectDao.insert(project); if (result == 1) { + LOGGER.info("Inserted project, domain={}, id={}.", project.getDomain(), project.getId()); return true; } else { + LOGGER.warn("Project insert returned unexpected row count, domain={}, result={}.", project.getDomain(), + result); return false; } - } catch (DalException e) { + } catch (RuntimeException e) { + LOGGER.error("Unable to insert project, domain={}.", project.getDomain(), e); Cat.logError(e); return false; } } public boolean insert(String domain) { + ensureInitialized(); + Project project = create(); project.setDomain(domain); @@ -192,6 +235,7 @@ public boolean insert(String domain) { return true; } catch (Exception ex) { + LOGGER.error("Unable to insert default project, domain={}.", domain, ex); Cat.logError(ex); } return false; @@ -199,7 +243,7 @@ public boolean insert(String domain) { protected void refresh() { try { - List projects = m_projectDao.findAll(ProjectEntity.READSET_FULL); + List projects = m_projectDao.findAll(); ConcurrentHashMap tmpDomainProjects = new ConcurrentHashMap(); ConcurrentHashMap tmpCmdbProjects = new ConcurrentHashMap(); ConcurrentHashMap tmpDomains = new ConcurrentHashMap(); @@ -219,18 +263,25 @@ protected void refresh() { m_domains = tmpDomains; m_domainToProjects = tmpDomainProjects; m_cmdbToProjects = tmpCmdbProjects; - } catch (DalException e) { + LOGGER.info("Refreshed projects, projectCount={}, cmdbDomainCount={}.", projects.size(), + tmpCmdbProjects.size()); + } catch (RuntimeException e) { + LOGGER.error("Unable to refresh ProjectService projects.", e); Cat.logError("initialize ProjectService error", e); } } public boolean update(Project project) { + ensureInitialized(); + m_domainToProjects.put(project.getDomain(), project); try { - m_projectDao.updateByPK(project, ProjectEntity.UPDATESET_FULL); + m_projectDao.updateByPK(project); + LOGGER.info("Updated project, domain={}, id={}.", project.getDomain(), project.getId()); return true; - } catch (DalException e) { + } catch (RuntimeException e) { + LOGGER.error("Unable to update project, domain={}, id={}.", project.getDomain(), project.getId(), e); Cat.logError(e); return false; } diff --git a/cat-core/src/main/java/com/dianping/cat/statistic/ServerStatisticManager.java b/cat-core/src/main/java/com/dianping/cat/statistic/ServerStatisticManager.java index 3e698f8f25..41e19c132c 100644 --- a/cat-core/src/main/java/com/dianping/cat/statistic/ServerStatisticManager.java +++ b/cat-core/src/main/java/com/dianping/cat/statistic/ServerStatisticManager.java @@ -18,11 +18,8 @@ */ package com.dianping.cat.statistic; -import org.unidal.lookup.annotation.Named; - import com.dianping.cat.statistic.ServerStatistic.Statistic; -@Named public class ServerStatisticManager { public ServerStatistic m_serverState = new ServerStatistic(); diff --git a/cat-core/src/main/java/com/dianping/cat/task/TaskManager.java b/cat-core/src/main/java/com/dianping/cat/task/TaskManager.java index aa8f451d8c..72c4b0f297 100644 --- a/cat-core/src/main/java/com/dianping/cat/task/TaskManager.java +++ b/cat-core/src/main/java/com/dianping/cat/task/TaskManager.java @@ -21,15 +21,11 @@ import com.dianping.cat.Cat; import com.dianping.cat.configuration.NetworkInterfaceManager; import com.dianping.cat.core.dal.Task; -import com.dianping.cat.core.dal.TaskDao; -import org.unidal.dal.jdbc.DalException; -import org.unidal.lookup.annotation.Inject; -import org.unidal.lookup.annotation.Named; +import com.dianping.cat.mybatis.TaskRepository; import java.util.Calendar; import java.util.Date; -@Named public class TaskManager { public static final int REPORT_HOUR = 0; @@ -46,12 +42,12 @@ public class TaskManager { private static final int STATUS_TODO = 1; - @Inject - private TaskDao m_taskDao; + private TaskRepository m_taskDao; - public boolean createTask(Date period, String domain, String name, TaskCreationPolicy prolicy) { + public boolean createTask(Date period, String domain, String name, TaskCreationPolicy policy) { + ensureTaskDao(); try { - if (prolicy.shouldCreateHourlyTask()) { + if (policy.shouldCreateHourlyTask()) { insertToDatabase(period, domain, name, REPORT_HOUR); } @@ -62,17 +58,17 @@ public boolean createTask(Date period, String domain, String name, TaskCreationP cal.add(Calendar.HOUR_OF_DAY, -hour); Date currentDay = cal.getTime(); - if (prolicy.shouldCreateDailyTask()) { + if (policy.shouldCreateDailyTask()) { insertToDatabase(new Date(currentDay.getTime() - ONE_DAY), domain, name, REPORT_DAILY); } - if (prolicy.shouldCreateWeeklyTask()) { + if (policy.shouldCreateWeeklyTask()) { int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); if (dayOfWeek == 7) { insertToDatabase(new Date(currentDay.getTime() - 7 * ONE_DAY), domain, name, REPORT_WEEK); } } - if (prolicy.shouldCreateMonthTask()) { + if (policy.shouldCreateMonthTask()) { int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); if (dayOfMonth == 1) { @@ -81,13 +77,14 @@ public boolean createTask(Date period, String domain, String name, TaskCreationP } } return true; - } catch (DalException e) { + } catch (RuntimeException e) { Cat.logError(e); return false; } } - protected void insertToDatabase(Date period, String domain, String name, int reportType) throws DalException { + protected void insertToDatabase(Date period, String domain, String name, int reportType) { + ensureTaskDao(); Task task = m_taskDao.createLocal(); task.setCreationDate(new Date()); @@ -100,6 +97,16 @@ protected void insertToDatabase(Date period, String domain, String name, int rep m_taskDao.insert(task); } + private void ensureTaskDao() { + if (m_taskDao == null) { + throw new IllegalStateException("TaskRepository is required for TaskManager."); + } + } + + public void setTaskDao(TaskRepository taskDao) { + m_taskDao = taskDao; + } + public enum TaskProlicy implements TaskCreationPolicy { ALL { diff --git a/cat-core/src/main/java/com/dianping/cat/task/TimerSyncTask.java b/cat-core/src/main/java/com/dianping/cat/task/TimerSyncTask.java index fa5f315268..8e9816222a 100644 --- a/cat-core/src/main/java/com/dianping/cat/task/TimerSyncTask.java +++ b/cat-core/src/main/java/com/dianping/cat/task/TimerSyncTask.java @@ -21,14 +21,17 @@ import com.dianping.cat.Cat; import com.dianping.cat.helper.TimeHelper; import com.dianping.cat.message.Transaction; -import org.unidal.helper.Threads; -import org.unidal.helper.Threads.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.dianping.cat.support.Threads; +import com.dianping.cat.support.Threads.Task; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; public class TimerSyncTask implements Task { + private static final Logger LOGGER = LoggerFactory.getLogger(TimerSyncTask.class); private static final long DURATION = TimeHelper.ONE_MINUTE; @@ -47,6 +50,7 @@ public static TimerSyncTask getInstance() { Threads.forGroup("Cat").start(m_instance); m_active = true; + LOGGER.info("TimerSyncTask started."); } } } @@ -60,7 +64,15 @@ public String getName() { public void register(SyncHandler handler) { synchronized (this) { + String name = handler.getName(); + + for (int i = m_handlers.size() - 1; i >= 0; i--) { + if (name.equals(m_handlers.get(i).getName())) { + m_handlers.remove(i); + } + } m_handlers.add(handler); + LOGGER.info("Registered timer sync handler, name={}, handlerCount={}.", name, m_handlers.size()); } } @@ -83,6 +95,7 @@ public void run() { t.setStatus(Transaction.SUCCESS); } catch (Exception e) { t.setStatus(e); + LOGGER.error("Timer sync handler failed, name={}.", handler.getName(), e); Cat.logError(e); } finally { t.complete(); @@ -98,9 +111,11 @@ public void run() { Thread.sleep(DURATION - duration); } } catch (InterruptedException e) { + LOGGER.warn("TimerSyncTask interrupted, shutting down.", e); active = false; } } + LOGGER.info("TimerSyncTask stopped."); } @Override diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/config-codegen.xml deleted file mode 100644 index 51b53764fb..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/config-codegen.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/config-dal.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/config-dal.xml deleted file mode 100644 index f13f028d32..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/config-dal.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - FROM
- WHERE = ${name}]]> - - - - - - - - - FROM
- ]]> - - - - - - - - - () - VALUES - () - ]]> - - - - - - FROM
- WHERE = ${name} - AND = ${domain} - ]]> - - - - - FROM
- WHERE = ${name} - ]]> - - - - SET =${content}, - =NOW() - WHERE = ${domain} - AND = ${name}; - ]]> - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/config-manifest.xml deleted file mode 100644 index dac88e7e0d..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/report-codegen.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/report-codegen.xml deleted file mode 100644 index 679d128a2e..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/report-codegen.xml +++ /dev/null @@ -1,447 +0,0 @@ - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-report-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-report-id}]]> - - - - - WHERE = ${key-report-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-report-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-report-id}]]> - - - - - WHERE = ${key-report-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-report-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-report-id}]]> - - - - - WHERE = ${key-report-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-report-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-report-id}]]> - - - - - WHERE = ${key-report-id}]]> - - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-id}]]> - - - () - VALUES()]]> - - - - - SET - WHERE = ${key-id}]]> - - - - - WHERE = ${key-id}]]> - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/report-dal.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/report-dal.xml deleted file mode 100644 index 984e64a260..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/report-dal.xml +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - () - VALUES - () - ]]> - - - - - - FROM
- WHERE = ${status} - - AND = ${consumer} - limit 1 - ]]> - - - - - SET =${consumer}, - =2, - =${start-date} - WHERE = 1 - AND = ${id}; - ]]> - - - - - SET =3, - =${end-date} - WHERE = 2 - AND = ${id}; - ]]> - - - - - SET =3, - =${end-date} - WHERE =4 - AND = ${id}; - - ]]> - - - - - SET =1, - WHERE = ${id}; - ]]> - - - - - SET =4, - =${end-date}, - = + 1 - WHERE = 2 - AND = ${id}; - ]]> - - - - - - - - - - - FROM
- WHERE = ${ip} - ]]> - - - - FROM
- ]]> - - - - () VALUES() - ON DUPLICATE KEY - UPDATE = ${domain}, - = NOW()]]> - - - - - - - - - - FROM
- ]]> - - - - - FROM
WHERE binary() = binary(${domain}) - ]]> - - - - - FROM
WHERE binary() = binary(${domain}) - ]]> - - - - () VALUES() - ON DUPLICATE KEY - UPDATE = ${domain}, - = NOW()]]> - - - - - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${key-report-id}]]> - - - - - FROM
- WHERE > ${start-id} - ORDER BY asc limit 1000 - ]]> - - - - - - - - - - - - - - - - - - - - FROM
- WHERE = ${period} - AND = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ]]> - - - - - - FROM
- WHERE = ${period} - AND = ${name} - ]]> - - - () - VALUES() - ]]> - - - - - - - - - - - - - - - - - - - - - () - VALUES - () - ]]> - - - - - - - FROM
- WHERE = ${period} - AND = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ]]> - - - - - - - WHERE = ${period} - AND = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ]]> - - - - - - - FROM
- WHERE = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ORDER BY DESC LIMIT ${limits} - ]]> - - - - - - - - - - - - FROM
- WHERE = ${period} - AND = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ]]> - - - - - - - WHERE = ${period} - AND = ${domain} - AND = ${name} - ]]> - - - - - - - - - - - - - FROM
- WHERE = ${period} - AND = ${domain} - AND = ${name} - AND binary() = binary(${domain}) - ]]> - - - - - - - WHERE = ${period} - AND = ${domain} - AND = ${name} - ]]> - - - - - - - - - - - - - - - - - - - FROM
- WHERE > ${start-id} - ORDER BY asc limit 1000 - ]]> - - - - - - - - - - - - - - - - - - - FROM
- WHERE > ${start-id} - ORDER BY asc limit 1000 - ]]> - - - - - - - - - - - - - - - - - - - - FROM
- WHERE > ${start-id} - ORDER BY asc limit 1000 - ]]> - - - - \ No newline at end of file diff --git a/cat-core/src/main/resources/META-INF/dal/jdbc/report-manifest.xml b/cat-core/src/main/resources/META-INF/dal/jdbc/report-manifest.xml deleted file mode 100644 index 17377c186d..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/jdbc/report-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-codegen.xml deleted file mode 100644 index 9e0e11abfa..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-codegen.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-manifest.xml deleted file mode 100644 index 8a0d7bad4a..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-model.xml deleted file mode 100644 index d0f804fe6a..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/atomic-message-config-model.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/business-report-config-codegen.xml deleted file mode 100644 index aed08431a3..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-codegen.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/business-report-config-manifest.xml deleted file mode 100644 index 640770c1b2..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/business-report-config-model.xml deleted file mode 100644 index 9134532732..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/business-report-config-model.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-codegen.xml deleted file mode 100644 index 2e1484a328..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-codegen.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-manifest.xml deleted file mode 100644 index a8be1d55b9..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-model.xml deleted file mode 100644 index 03b0556e15..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/report-reload-config-model.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/sample-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/sample-config-codegen.xml deleted file mode 100644 index 29f0f52948..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/sample-config-codegen.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/sample-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/sample-config-manifest.xml deleted file mode 100644 index a03ec502b2..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/sample-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/sample-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/sample-config-model.xml deleted file mode 100644 index 4d1b8bab93..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/sample-config-model.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/server-codegen.xml deleted file mode 100644 index 69a5437ed8..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-codegen.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/server-config-codegen.xml deleted file mode 100644 index 891e47b1e8..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-config-codegen.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/server-config-manifest.xml deleted file mode 100644 index ef33792865..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/server-config-model.xml deleted file mode 100644 index fcbbaf0094..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-config-model.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-codegen.xml deleted file mode 100644 index cfd61d2f9d..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-codegen.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml deleted file mode 100644 index 9f0db7fa85..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-model.xml deleted file mode 100644 index ab5875cb9c..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-filter-config-model.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/server-manifest.xml deleted file mode 100644 index e9dd52b418..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/server-model.xml b/cat-core/src/main/resources/META-INF/dal/model/server-model.xml deleted file mode 100644 index 2053fe3629..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/server-model.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-codegen.xml deleted file mode 100644 index d253714577..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-codegen.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-manifest.xml deleted file mode 100644 index 31513f9a41..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-model.xml b/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-model.xml deleted file mode 100644 index 26585fe38b..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/tp-value-statistic-config-model.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml b/cat-core/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml deleted file mode 100644 index 548fceeb43..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-codegen.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml b/cat-core/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml deleted file mode 100644 index d873e11433..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-manifest.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-model.xml b/cat-core/src/main/resources/META-INF/dal/model/url-pattern-model.xml deleted file mode 100644 index f8d6e814d0..0000000000 --- a/cat-core/src/main/resources/META-INF/dal/model/url-pattern-model.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cat-core/src/main/resources/META-INF/plexus/components.xml b/cat-core/src/main/resources/META-INF/plexus/components.xml deleted file mode 100644 index cde672900d..0000000000 --- a/cat-core/src/main/resources/META-INF/plexus/components.xml +++ /dev/null @@ -1,700 +0,0 @@ - - - - - com.dianping.cat.analysis.MessageConsumer - com.dianping.cat.analysis.RealtimeConsumer - - - com.dianping.cat.analysis.MessageAnalyzerManager - - - com.dianping.cat.statistic.ServerStatisticManager - - - - - com.dianping.cat.config.server.ServerConfigManager - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.service.HostinfoService - com.dianping.cat.service.HostinfoService - - - com.dianping.cat.core.dal.HostinfoDao - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.service.IpService - com.dianping.cat.service.IpService - - - com.dianping.cat.service.IpService2 - com.dianping.cat.service.IpService2 - - - com.dianping.cat.task.TaskManager - com.dianping.cat.task.TaskManager - - - com.dianping.cat.core.dal.TaskDao - - - - - com.dianping.cat.statistic.ServerStatisticManager - com.dianping.cat.statistic.ServerStatisticManager - - - com.dianping.cat.report.DomainValidator - com.dianping.cat.report.DomainValidator - - - com.dianping.cat.config.content.ContentFetcher - com.dianping.cat.config.content.LocalResourceContentFetcher - - - com.dianping.cat.config.server.ServerFilterConfigManager - com.dianping.cat.config.server.ServerFilterConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.message.PathBuilder - com.dianping.cat.message.DefaultPathBuilder - - - com.dianping.cat.analysis.MessageAnalyzerManager - com.dianping.cat.analysis.DefaultMessageAnalyzerManager - - - com.dianping.cat.analysis.TcpSocketReceiver - com.dianping.cat.analysis.TcpSocketReceiver - - - com.dianping.cat.config.server.ServerConfigManager - - - com.dianping.cat.analysis.MessageHandler - - - com.dianping.cat.statistic.ServerStatisticManager - - - - - com.dianping.cat.analysis.MessageHandler - com.dianping.cat.analysis.DefaultMessageHandler - - - com.dianping.cat.analysis.MessageConsumer - - - - - com.dianping.cat.config.sample.SampleConfigManager - com.dianping.cat.config.sample.SampleConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - com.dianping.cat.config.business.BusinessConfigManager - com.dianping.cat.config.business.BusinessConfigManager - - - com.dianping.cat.core.config.BusinessConfigDao - - - - - com.dianping.cat.config.ReportReloadConfigManager - com.dianping.cat.config.ReportReloadConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - org.unidal.initialization.Module - cat-core - com.dianping.cat.CatCoreModule - - - com.dianping.cat.report.ReportBucketManager - com.dianping.cat.report.DefaultReportBucketManager - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.report.ReportBucket - com.dianping.cat.report.LocalReportBucket - per-lookup - - - com.dianping.cat.message.PathBuilder - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.message.storage.MessageBucket - local - com.dianping.cat.message.storage.LocalMessageBucket - per-lookup - - - com.dianping.cat.report.server.RemoteServersManager - com.dianping.cat.report.server.RemoteServersManager - - - com.dianping.cat.report.server.ServersUpdaterManager - com.dianping.cat.report.server.ServersUpdaterManager - - - com.dianping.cat.report.server.ServersUpdater - - - com.dianping.cat.report.server.RemoteServersManager - - - - - com.dianping.cat.config.transaction.TpValueStatisticConfigManager - com.dianping.cat.config.transaction.TpValueStatisticConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - com.dianping.cat.config.server.ServerConfigManager - - - - - com.dianping.cat.config.AtomicMessageConfigManager - com.dianping.cat.config.AtomicMessageConfigManager - - - com.dianping.cat.core.config.ConfigDao - - - com.dianping.cat.config.content.ContentFetcher - - - - - org.unidal.dal.jdbc.datasource.DataSourceProvider - org.unidal.dal.jdbc.datasource.DefaultDataSourceProvider - - datasources.xml - CAT_HOME - /data/appdatas/cat/ - - - - org.unidal.dal.jdbc.mapping.TableProvider - business-config - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - business_config - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - config - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - config - cat - - - - com.dianping.cat.core.config.BusinessConfigDao - com.dianping.cat.core.config.BusinessConfigDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.config.ConfigDao - com.dianping.cat.core.config.ConfigDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - org.unidal.dal.jdbc.mapping.TableProvider - daily-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - daily_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - dailyreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - dailyreport - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - hostinfo - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - hostinfo - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - monthly-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - monthly_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - monthreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - monthreport - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - project - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - project - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - report - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - report - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - task - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - task - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - weekly-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - weekly_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - weeklyreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - weeklyreport - cat - - - - com.dianping.cat.core.dal.DailyReportContentDao - com.dianping.cat.core.dal.DailyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.DailyReportDao - com.dianping.cat.core.dal.DailyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HostinfoDao - com.dianping.cat.core.dal.HostinfoDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.MonthlyReportContentDao - com.dianping.cat.core.dal.MonthlyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.MonthlyReportDao - com.dianping.cat.core.dal.MonthlyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.ProjectDao - com.dianping.cat.core.dal.ProjectDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HourlyReportDao - com.dianping.cat.core.dal.HourlyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HourlyReportContentDao - com.dianping.cat.core.dal.HourlyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.TaskDao - com.dianping.cat.core.dal.TaskDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.WeeklyReportContentDao - com.dianping.cat.core.dal.WeeklyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.WeeklyReportDao - com.dianping.cat.core.dal.WeeklyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - org.unidal.dal.jdbc.mapping.TableProvider - daily-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - daily_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - dailyreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - dailyreport - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - hostinfo - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - hostinfo - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - monthly-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - monthly_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - monthreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - monthreport - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - project - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - project - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - report - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - report - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - task - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - task - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - weekly-report-content - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - weekly_report_content - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - weeklyreport - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - weeklyreport - cat - - - - com.dianping.cat.core.dal.DailyReportContentDao - com.dianping.cat.core.dal.DailyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.DailyReportDao - com.dianping.cat.core.dal.DailyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HostinfoDao - com.dianping.cat.core.dal.HostinfoDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.MonthlyReportContentDao - com.dianping.cat.core.dal.MonthlyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.MonthlyReportDao - com.dianping.cat.core.dal.MonthlyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.ProjectDao - com.dianping.cat.core.dal.ProjectDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HourlyReportDao - com.dianping.cat.core.dal.HourlyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.HourlyReportContentDao - com.dianping.cat.core.dal.HourlyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.TaskDao - com.dianping.cat.core.dal.TaskDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.WeeklyReportContentDao - com.dianping.cat.core.dal.WeeklyReportContentDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.dal.WeeklyReportDao - com.dianping.cat.core.dal.WeeklyReportDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - org.unidal.dal.jdbc.mapping.TableProvider - business-config - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - business_config - cat - - - - org.unidal.dal.jdbc.mapping.TableProvider - config - org.unidal.dal.jdbc.mapping.SimpleTableProvider - - config - cat - - - - com.dianping.cat.core.config.BusinessConfigDao - com.dianping.cat.core.config.BusinessConfigDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - com.dianping.cat.core.config.ConfigDao - com.dianping.cat.core.config.ConfigDao - - - org.unidal.dal.jdbc.QueryEngine - - - - - diff --git a/cat-core/src/main/resources/META-INF/wizard/jdbc/wizard.xml b/cat-core/src/main/resources/META-INF/wizard/jdbc/wizard.xml index f4584a0d62..408182a272 100644 --- a/cat-core/src/main/resources/META-INF/wizard/jdbc/wizard.xml +++ b/cat-core/src/main/resources/META-INF/wizard/jdbc/wizard.xml @@ -2,35 +2,37 @@ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://127.0.0.1:3306/cat root useUnicode=true&autoReconnect=true -
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
- - -
-
- +
+
+
+
+
+
+ + +
+
+ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://127.0.0.1:3306/cat root @@ -47,7 +49,7 @@ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://127.0.0.1:3306/cat root @@ -64,7 +66,7 @@ - com.mysql.jdbc.Driver + com.mysql.cj.jdbc.Driver jdbc:mysql://127.0.0.1:3306/cat root diff --git a/cat-core/src/main/resources/mybatis/mapper/BusinessConfigMapper.xml b/cat-core/src/main/resources/mybatis/mapper/BusinessConfigMapper.xml new file mode 100644 index 0000000000..5abb439bce --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/BusinessConfigMapper.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + id , + name , + domain , + content , + create_time , + update_time + + + + + id = #{id} , + name = #{name} , + domain = #{domain} , + content = #{content} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_business_config + + + + + + + + + delete from t_business_config where id = #{id} + + + + UPDATE t_business_config + + WHERE id = #{id} + + + + + + + + UPDATE t_business_config SET content=#{record.content}, update_time=NOW() where domain = #{record.domain} and name = #{record.name} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/BusinessReportMapper.xml b/cat-core/src/main/resources/mybatis/mapper/BusinessReportMapper.xml new file mode 100644 index 0000000000..15f25a60ae --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/BusinessReportMapper.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + id , + type , + name , + ip , + product_line , + period , + content , + create_time , + update_time + + + + + id = #{id} , + type = #{type} , + name = #{name} , + ip = #{ip} , + product_line = #{productLine} , + period = #{period} , + content = #{content} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_business_report + + + + + + + + + delete from t_business_report where id = #{id} + + + + UPDATE t_business_report + + WHERE id = #{id} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/ConfigMapper.xml b/cat-core/src/main/resources/mybatis/mapper/ConfigMapper.xml new file mode 100644 index 0000000000..b739a47a59 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/ConfigMapper.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + id , + name , + content , + create_time , + update_time + + + + + id = #{id} , + name = #{name} , + content = #{content} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_config + + + + + + + + + + + delete from t_config where id = #{id} + + + + UPDATE t_config + + WHERE id = #{id} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/DailyReportContentMapper.xml b/cat-core/src/main/resources/mybatis/mapper/DailyReportContentMapper.xml new file mode 100644 index 0000000000..3ba5a8656a --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/DailyReportContentMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + report_id , + content , + period , + create_time , + update_time + + + + + report_id = #{reportId} , + content = #{content} , + period = #{period} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_daily_report_content + + + + + + + + + delete from t_daily_report_content where report_id = #{reportId} + + + + UPDATE t_daily_report_content + + WHERE report_id = #{reportId} + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/DailyReportMapper.xml b/cat-core/src/main/resources/mybatis/mapper/DailyReportMapper.xml new file mode 100644 index 0000000000..f1afd9224c --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/DailyReportMapper.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + id , + name , + ip , + domain , + period , + type , + create_time + + + + + id = #{id} , + name = #{name} , + ip = #{ip} , + domain = #{domain} , + period = #{period} , + type = #{type} , + create_time = #{createTime} + + + + + INSERT INTO t_daily_report + + + + + + + + + + + delete from t_daily_report where id = #{id} + + + + DELETE from t_daily_report + where period = #{period} + and domain = #{domain} + and name = #{name} + and BINARY(domain) = BINARY(#{domain}) + + + + UPDATE t_daily_report + + WHERE id = #{id} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/HostInfoMapper.xml b/cat-core/src/main/resources/mybatis/mapper/HostInfoMapper.xml new file mode 100644 index 0000000000..6678b0ce3b --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/HostInfoMapper.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + id , + ip , + domain , + hostname , + create_time , + update_time + + + + + id = #{id} , + ip = #{ip} , + domain = #{domain} , + hostname = #{hostname} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_host_info + + + + + + + + + delete from t_host_info where id = #{id} + + + + UPDATE t_host_info + + WHERE id = #{id} + + + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/HourlyReportContentMapper.xml b/cat-core/src/main/resources/mybatis/mapper/HourlyReportContentMapper.xml new file mode 100644 index 0000000000..f50b92258c --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/HourlyReportContentMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + report_id , + content , + period , + create_time , + update_time + + + + + report_id = #{reportId} , + content = #{content} , + period = #{period} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_hourly_report_content + + + + + + + + + delete from t_hourly_report_content where report_id = #{reportId} + + + + UPDATE t_hourly_report_content + + WHERE report_id = #{reportId} + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/HourlyReportMapper.xml b/cat-core/src/main/resources/mybatis/mapper/HourlyReportMapper.xml new file mode 100644 index 0000000000..ba1e8ecdcf --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/HourlyReportMapper.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + id , + type , + name , + ip , + domain , + period , + create_time + + + + + id = #{id} , + type = #{type} , + name = #{name} , + ip = #{ip} , + domain = #{domain} , + period = #{period} , + create_time = #{createTime} + + + + + INSERT INTO t_hourly_report + + + + + + + + + delete from t_hourly_report where id = #{id} + + + + UPDATE t_hourly_report + + WHERE id = #{id} + + + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/MonthReportMapper.xml b/cat-core/src/main/resources/mybatis/mapper/MonthReportMapper.xml new file mode 100644 index 0000000000..5a0c658404 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/MonthReportMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + id , + name , + ip , + domain , + period , + type , + create_time + + + + + id = #{id} , + name = #{name} , + ip = #{ip} , + domain = #{domain} , + period = #{period} , + type = #{type} , + create_time = #{createTime} + + + + + INSERT INTO t_monthly_report + + + + + + + + + delete from t_monthly_report where id = #{id} + + + + UPDATE t_monthly_report + + WHERE id = #{id} + + + + + + DELETE from t_monthly_report where period = #{record.period} and domain = #{record.domain} and name = #{record.name} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/MonthlyReportContentMapper.xml b/cat-core/src/main/resources/mybatis/mapper/MonthlyReportContentMapper.xml new file mode 100644 index 0000000000..4c93b3644f --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/MonthlyReportContentMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + report_id , + content , + period , + create_time , + update_time + + + + + report_id = #{reportId} , + content = #{content} , + period = #{period} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_monthly_report_content + + + + + + + + + delete from t_monthly_report_content where report_id = #{reportId} + + + + UPDATE t_monthly_report_content + + WHERE report_id = #{reportId} + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/OperationMapper.xml b/cat-core/src/main/resources/mybatis/mapper/OperationMapper.xml new file mode 100644 index 0000000000..58f4f2b0b2 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/OperationMapper.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + id , + `user` , + module , + operation , + operation_time , + content , + create_time , + update_time + + + + + id = #{id} , + `user` = #{user} , + module = #{module} , + operation = #{operation} , + operation_time = #{operationTime} , + content = #{content} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_operation + + + + + + + + + delete from t_operation where id = #{id} + + + + UPDATE t_operation + + WHERE id = #{id} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/ProjectMapper.xml b/cat-core/src/main/resources/mybatis/mapper/ProjectMapper.xml new file mode 100644 index 0000000000..06a10c42e7 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/ProjectMapper.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + id , + domain , + cmdb_domain , + level , + bu , + cmdb_product_line , + owner , + email , + phone , + create_time , + update_time + + + + + id = #{id} , + domain = #{domain} , + cmdb_domain = #{cmdbDomain} , + level = #{level} , + bu = #{bu} , + cmdb_product_line = #{cmdbProductline} , + owner = #{owner} , + email = #{email} , + phone = #{phone} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_project + + + + + + + + + delete from t_project where id = #{id} + + + + UPDATE t_project + + WHERE id = #{id} + + + + + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/TaskMapper.xml b/cat-core/src/main/resources/mybatis/mapper/TaskMapper.xml new file mode 100644 index 0000000000..753421840a --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/TaskMapper.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + id , + producer , + consumer , + failure_count , + report_name , + report_domain , + report_period , + status , + task_type , + create_time , + start_time , + end_time , + update_time + + + + + id = #{id} , + producer = #{producer} , + consumer = #{consumer} , + failure_count = #{failureCount} , + report_name = #{reportName} , + report_domain = #{reportDomain} , + report_period = #{reportPeriod} , + status = #{status} , + task_type = #{taskType} , + create_time = #{createTime} , + start_time = #{startTime} , + end_time = #{endTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_task + + + + + + + + + delete from t_task where id = #{id} + + + + UPDATE t_task + + WHERE id = #{id} + + + + + + UPDATE t_task SET consumer=#{record.consumer}, status=2, start_time=#{record.startTime} where status = 1 and id = #{record.id} + + + + UPDATE t_task SET status=3, end_time=#{record.endTime} where status = 2 and id = #{record.id} + + + + UPDATE t_task SET status=3, end_time=#{record.endTime} where status =4 and id = #{record.id} + + + + UPDATE t_task SET status=1 where id = #{record.id} + + + + UPDATE t_task SET status=4, end_time=#{record.endTime}, failure_count = failure_count + 1 where status = 2 and id = #{record.id} + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/WeeklyReportContentMapper.xml b/cat-core/src/main/resources/mybatis/mapper/WeeklyReportContentMapper.xml new file mode 100644 index 0000000000..53a38868e5 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/WeeklyReportContentMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + report_id , + content , + period , + create_time , + update_time + + + + + report_id = #{reportId} , + content = #{content} , + period = #{period} , + create_time = #{createTime} , + update_time = #{updateTime} + + + + + INSERT INTO t_weekly_report_content + + + + + + + + + delete from t_weekly_report_content where report_id = #{reportId} + + + + UPDATE t_weekly_report_content + + WHERE report_id = #{reportId} + + + + + diff --git a/cat-core/src/main/resources/mybatis/mapper/WeeklyReportMapper.xml b/cat-core/src/main/resources/mybatis/mapper/WeeklyReportMapper.xml new file mode 100644 index 0000000000..0524c9f382 --- /dev/null +++ b/cat-core/src/main/resources/mybatis/mapper/WeeklyReportMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + id , + name , + ip , + domain , + period , + type , + create_time + + + + + id = #{id} , + name = #{name} , + ip = #{ip} , + domain = #{domain} , + period = #{period} , + type = #{type} , + create_time = #{createTime} + + + + + INSERT INTO t_weekly_report + + + + + + + + + delete from t_weekly_report where id = #{id} + + + + UPDATE t_weekly_report + + WHERE id = #{id} + + + + + + DELETE from t_weekly_report where period = #{record.period} and domain = #{record.domain} and name = #{record.name} + + + diff --git a/cat-core/src/test/java/com/dianping/cat/analysis/AbstractMessageAnalyzerTest.java b/cat-core/src/test/java/com/dianping/cat/analysis/AbstractMessageAnalyzerTest.java index ec86cc021d..97d70a2b8f 100644 --- a/cat-core/src/test/java/com/dianping/cat/analysis/AbstractMessageAnalyzerTest.java +++ b/cat-core/src/test/java/com/dianping/cat/analysis/AbstractMessageAnalyzerTest.java @@ -20,14 +20,13 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Threads; -import org.unidal.lookup.ComponentTestCase; +import com.dianping.cat.support.Threads; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.ReportManager; -public class AbstractMessageAnalyzerTest extends ComponentTestCase { +public class AbstractMessageAnalyzerTest { @Test public void testTimeOut() throws InterruptedException { diff --git a/cat-core/src/test/java/com/dianping/cat/analysis/PeriodTaskTest.java b/cat-core/src/test/java/com/dianping/cat/analysis/PeriodTaskTest.java index a924826546..0c51f7c0e8 100644 --- a/cat-core/src/test/java/com/dianping/cat/analysis/PeriodTaskTest.java +++ b/cat-core/src/test/java/com/dianping/cat/analysis/PeriodTaskTest.java @@ -20,13 +20,12 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.message.spi.DefaultMessageTree; import com.dianping.cat.message.spi.MessageTree; import com.dianping.cat.report.ReportManager; -public class PeriodTaskTest extends ComponentTestCase { +public class PeriodTaskTest { @Test public void test() throws Exception { diff --git a/cat-core/src/test/java/com/dianping/cat/message/DefaultMessagePathBuilderTest.java b/cat-core/src/test/java/com/dianping/cat/message/DefaultMessagePathBuilderTest.java index 3b9e86d404..9221f39bc2 100644 --- a/cat-core/src/test/java/com/dianping/cat/message/DefaultMessagePathBuilderTest.java +++ b/cat-core/src/test/java/com/dianping/cat/message/DefaultMessagePathBuilderTest.java @@ -21,17 +21,17 @@ import java.text.Format; import java.text.MessageFormat; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.TimeZone; import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Splitters; public class DefaultMessagePathBuilderTest { private String convertToHex(String ip) { - List items = Splitters.by(".").noEmptyItem().split(ip); + List items = Arrays.asList(ip.split("\\.")); byte[] bytes = new byte[4]; for (int i = 0; i < 4; i++) { @@ -61,7 +61,7 @@ public void testParseMessageIdFromPath() throws Exception { String path = "20120807/14/Cat-Cat-192.168.64.153"; Object[] objects = format.parse(path); Date timestamp = (Date) objects[0]; - List parts = Splitters.by('-').split((String) objects[1]); + List parts = Arrays.asList(((String) objects[1]).split("-")); String domain = parts.get(1); String ip = parts.get(2); String id = domain + "-" + convertToHex(ip) + "-" + timestamp.getTime() / 3600000L + "-0"; diff --git a/cat-core/src/test/java/com/dianping/cat/server/ServerConfigVisitorTest.java b/cat-core/src/test/java/com/dianping/cat/server/ServerConfigVisitorTest.java index b206f6a0f2..887254b53d 100644 --- a/cat-core/src/test/java/com/dianping/cat/server/ServerConfigVisitorTest.java +++ b/cat-core/src/test/java/com/dianping/cat/server/ServerConfigVisitorTest.java @@ -22,7 +22,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.helper.Files; import org.xml.sax.SAXException; import com.dianping.cat.config.server.ServerConfigVisitor; @@ -34,7 +33,7 @@ public class ServerConfigVisitorTest { @Test public void test() throws IOException, SAXException { - String server = Files.forIO().readFrom(getClass().getResourceAsStream("server.xml"), "utf-8"); + String server = readResource("server.xml"); ServerConfig serverConfig01 = DefaultSaxParser.parse(server); ServerConfig serverConfig02 = DefaultSaxParser.parse(server); @@ -49,11 +48,14 @@ public void test() throws IOException, SAXException { ServerConfigVisitor visitor02 = new ServerConfigVisitor(server02); visitor02.visitServer(default02); - String expected01 = Files.forIO().readFrom(getClass().getResourceAsStream("server01.xml"), "utf-8"); + String expected01 = readResource("server01.xml"); Assert.assertEquals(expected01.replace("\r", ""), default01.toString().replace("\r", "")); - String expected02 = Files.forIO().readFrom(getClass().getResourceAsStream("server02.xml"), "utf-8"); + String expected02 = readResource("server02.xml"); Assert.assertEquals(expected02.replace("\r", ""), default02.toString().replace("\r", "")); } + private String readResource(String name) throws IOException { + return new String(getClass().getResourceAsStream(name).readAllBytes(), java.nio.charset.StandardCharsets.UTF_8); + } } diff --git a/cat-core/src/test/java/com/dianping/cat/service/DefaultReportManagerTest.java b/cat-core/src/test/java/com/dianping/cat/service/DefaultReportManagerTest.java index 4066fefe39..67c896a31e 100644 --- a/cat-core/src/test/java/com/dianping/cat/service/DefaultReportManagerTest.java +++ b/cat-core/src/test/java/com/dianping/cat/service/DefaultReportManagerTest.java @@ -30,12 +30,11 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.unidal.dal.jdbc.DalException; import com.dianping.cat.core.dal.HourlyReport; import com.dianping.cat.core.dal.HourlyReportContent; -import com.dianping.cat.core.dal.HourlyReportContentDao; -import com.dianping.cat.core.dal.HourlyReportDao; +import com.dianping.cat.mybatis.HourlyReportContentRepository; +import com.dianping.cat.mybatis.HourlyReportRepository; import com.dianping.cat.report.DefaultReportManager; import com.dianping.cat.report.DefaultReportManager.StoragePolicy; import com.dianping.cat.report.DomainValidator; @@ -136,6 +135,8 @@ public void testStoreReport() { Assert.assertEquals(3, m_reportContentDao.count); Assert.assertEquals(3, m_hourlyReportDao.count); Assert.assertEquals(3, m_bucketInsertCount); + Assert.assertNotNull(m_hourlyReportDao.creationDate); + Assert.assertNotNull(m_reportContentDao.creationDate); } public class MockBucketManager implements ReportBucketManager { @@ -155,23 +156,29 @@ public void clearOldReports() { } - public class MockHourlyReportDao extends HourlyReportDao { + public class MockHourlyReportDao extends HourlyReportRepository { public int count; + public Date creationDate; + @Override - public int insert(HourlyReport proto) throws DalException { + public int insert(HourlyReport proto) { + creationDate = proto.getCreationDate(); return count++; } } - public class MockReportContentDao extends HourlyReportContentDao { + public class MockReportContentDao extends HourlyReportContentRepository { public int count; + public Date creationDate; + @Override - public int insert(HourlyReportContent proto) throws DalException { + public int insert(HourlyReportContent proto) { + creationDate = proto.getCreationDate(); return count++; } diff --git a/cat-core/src/test/java/com/dianping/cat/service/IpServiceTest.java b/cat-core/src/test/java/com/dianping/cat/service/IpServiceTest.java index 7cb71fba92..1c6c5530ed 100644 --- a/cat-core/src/test/java/com/dianping/cat/service/IpServiceTest.java +++ b/cat-core/src/test/java/com/dianping/cat/service/IpServiceTest.java @@ -22,12 +22,11 @@ import java.util.List; import org.junit.Test; -import org.unidal.helper.Threads; -import org.unidal.lookup.ComponentTestCase; +import com.dianping.cat.support.Threads; import com.dianping.cat.service.IpService.IpInfo; -public class IpServiceTest extends ComponentTestCase { +public class IpServiceTest { IpService2 service; List result = new ArrayList(); @@ -39,7 +38,7 @@ public void getSystemTime() throws Exception { @Test public void test() throws Exception { - IpService service = (IpService) lookup(IpService.class); + IpService service = new IpService(); for (int i = 0; i < 10000; i++) { String ip = i % 255 + "." + i % 255 + "." + i % 255 + "." + i % 255; @@ -55,7 +54,7 @@ public void test() throws Exception { @Test public void test2() throws InterruptedException { - service = (IpService2) lookup(IpService2.class); + service = new IpService2(); int count = 1000; for (int j = 0; j < count; j++) { diff --git a/cat-core/src/test/java/com/dianping/cat/storage/BucketConcurrentTest.java b/cat-core/src/test/java/com/dianping/cat/storage/BucketConcurrentTest.java index 934018b177..a8a3f4e8db 100644 --- a/cat-core/src/test/java/com/dianping/cat/storage/BucketConcurrentTest.java +++ b/cat-core/src/test/java/com/dianping/cat/storage/BucketConcurrentTest.java @@ -26,18 +26,22 @@ import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.unidal.lookup.ComponentTestCase; - -import com.dianping.cat.report.ReportBucket; -import com.dianping.cat.report.ReportBucketManager; - -@RunWith(JUnit4.class) -@Ignore -public class BucketConcurrentTest extends ComponentTestCase { +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.message.DefaultPathBuilder; +import com.dianping.cat.report.DefaultReportBucketManager; +import com.dianping.cat.report.LocalReportBucket; +import com.dianping.cat.report.ReportBucket; +import com.dianping.cat.report.ReportBucketFactory; +import com.dianping.cat.report.ReportBucketManager; + +@RunWith(JUnit4.class) +@Ignore +public class BucketConcurrentTest { @BeforeClass public static void beforeClass() { new File("target/bucket/concurrent/bytes").delete(); @@ -45,11 +49,11 @@ public static void beforeClass() { new File("target/bucket/concurrent/data").delete(); } - @Test - public void testStringBucket() throws Exception { - long timestamp = System.currentTimeMillis(); - ReportBucketManager manager = lookup(ReportBucketManager.class); - final ReportBucket bucket = manager.getReportBucket(timestamp, "concurrent/data", 0); + @Test + public void testStringBucket() throws Exception { + long timestamp = System.currentTimeMillis(); + ReportBucketManager manager = createReportBucketManager(); + final ReportBucket bucket = manager.getReportBucket(timestamp, "concurrent/data", 0); ExecutorService pool = Executors.newFixedThreadPool(10); for (int p = 0; p < 10; p++) { @@ -111,6 +115,28 @@ public void run() { String t2 = bucket.findById(id); Assert.assertEquals("Unable to find data after stored it.", t1, t2); - } - } -} + } + } + + private ReportBucketManager createReportBucketManager() { + DefaultReportBucketManager manager = new DefaultReportBucketManager(); + + manager.setBucketFactory(new MockReportBucketFactory()); + manager.setConfigManager(new ServerConfigManager()); + manager.initialize(); + return manager; + } + + private static class MockReportBucketFactory implements ReportBucketFactory { + + @Override + public ReportBucket createReportBucket(String name, java.util.Date timestamp, int index) throws IOException { + LocalReportBucket bucket = new LocalReportBucket(); + + bucket.setConfigManager(new ServerConfigManager()); + bucket.setPathBuilder(new DefaultPathBuilder()); + bucket.initialize(name, timestamp, index); + return bucket; + } + } +} diff --git a/cat-core/src/test/java/com/dianping/cat/storage/StringBucketTestCase.java b/cat-core/src/test/java/com/dianping/cat/storage/StringBucketTestCase.java index edd690e60f..d96a9cd8a7 100644 --- a/cat-core/src/test/java/com/dianping/cat/storage/StringBucketTestCase.java +++ b/cat-core/src/test/java/com/dianping/cat/storage/StringBucketTestCase.java @@ -28,11 +28,10 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.unidal.lookup.ComponentTestCase; import com.dianping.cat.report.ReportBucket; -public abstract class StringBucketTestCase extends ComponentTestCase { +public abstract class StringBucketTestCase { protected final static int threadNum = 200;// notice: max 9, for creating asc order id bellow @@ -76,13 +75,7 @@ protected CountDownLatch createLatch() { } @Before - @Override public void setUp() throws IOException { - try { - super.setUp(); - } catch (Exception e1) { - e1.printStackTrace(); - } try { pool = Executors.newFixedThreadPool(threadNum); bucket = createBucket(); @@ -94,9 +87,7 @@ public void setUp() throws IOException { protected abstract ReportBucket createBucket() throws Exception; @After - @Override public void tearDown() throws Exception { - super.tearDown(); bucket.close(); } diff --git a/cat-core/src/test/java/com/dianping/cat/storage/report/LocalReportBucketTest.java b/cat-core/src/test/java/com/dianping/cat/storage/report/LocalReportBucketTest.java index adc8a9c9b5..cefbdb2ed3 100644 --- a/cat-core/src/test/java/com/dianping/cat/storage/report/LocalReportBucketTest.java +++ b/cat-core/src/test/java/com/dianping/cat/storage/report/LocalReportBucketTest.java @@ -24,6 +24,8 @@ import org.junit.After; +import com.dianping.cat.config.server.ServerConfigManager; +import com.dianping.cat.message.DefaultPathBuilder; import com.dianping.cat.report.LocalReportBucket; import com.dianping.cat.report.ReportBucket; import com.dianping.cat.storage.StringBucketTestCase; @@ -32,7 +34,10 @@ public class LocalReportBucketTest extends StringBucketTestCase { @Override protected ReportBucket createBucket() throws Exception, IOException { - ReportBucket bucket = lookup(ReportBucket.class, String.class.getName() + "-report"); + LocalReportBucket bucket = new LocalReportBucket(); + + bucket.setConfigManager(new ServerConfigManager()); + bucket.setPathBuilder(new DefaultPathBuilder()); bucket.initialize("cat", new Date(), 0); return bucket; } diff --git a/cat-core/src/test/java/com/dianping/cat/task/TaskManagerTest.java b/cat-core/src/test/java/com/dianping/cat/task/TaskManagerTest.java index 942f713374..a260ff8c17 100644 --- a/cat-core/src/test/java/com/dianping/cat/task/TaskManagerTest.java +++ b/cat-core/src/test/java/com/dianping/cat/task/TaskManagerTest.java @@ -27,7 +27,6 @@ import org.junit.Assert; import org.junit.Test; -import org.unidal.dal.jdbc.DalException; import com.dianping.cat.task.TaskManager.TaskProlicy; @@ -79,7 +78,7 @@ public static class MockTaskManager extends TaskManager { private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); @Override - protected void insertToDatabase(Date period, String ip, String domain, int reportType) throws DalException { + protected void insertToDatabase(Date period, String ip, String domain, int reportType) { Set lists = m_results.get(reportType); if (lists == null) { diff --git a/cat-core/src/test/resources/com/dianping/cat/analysis/DefaultMessageAnalyzerManagerTest.xml b/cat-core/src/test/resources/com/dianping/cat/analysis/DefaultMessageAnalyzerManagerTest.xml deleted file mode 100644 index 541a789112..0000000000 --- a/cat-core/src/test/resources/com/dianping/cat/analysis/DefaultMessageAnalyzerManagerTest.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - com.dianping.cat.analysis.MessageAnalyzer - mock1 - com.dianping.cat.analysis.Configurator$MockAnalyzer1 - per-lookup - - - com.dianping.cat.analysis.MessageAnalyzer - mock2 - com.dianping.cat.analysis.Configurator$MockAnalyzer2 - per-lookup - - - com.dianping.cat.analysis.MessageAnalyzer - state - com.dianping.cat.analysis.Configurator$MockAnalyzer3 - per-lookup - - - diff --git a/cat-core/src/test/resources/com/dianping/cat/message/codec/HtmlMessageCodecTest.xml b/cat-core/src/test/resources/com/dianping/cat/message/codec/HtmlMessageCodecTest.xml deleted file mode 100644 index ff489d85f2..0000000000 --- a/cat-core/src/test/resources/com/dianping/cat/message/codec/HtmlMessageCodecTest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - com.dianping.cat.message.MessageProducer - com.dianping.cat.message.internal.DefaultMessageProducer - - - com.dianping.cat.message.io.MessageSender - in-memory - - - - - diff --git a/cat-core/src/test/resources/log4j.properties b/cat-core/src/test/resources/log4j.properties new file mode 100644 index 0000000000..42a4b984de --- /dev/null +++ b/cat-core/src/test/resources/log4j.properties @@ -0,0 +1,4 @@ +log4j.rootLogger=WARN, CONSOLE +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] [%-5p] [%c{1}] %m%n diff --git a/cat-core/src/test/resources/logback-test.xml b/cat-core/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..31b2c13de8 --- /dev/null +++ b/cat-core/src/test/resources/logback-test.xml @@ -0,0 +1,11 @@ + + + + + [%d{HH:mm:ss.SSS}] [%-5level] [%logger{36}] %msg%n + + + + + + diff --git a/cat-hadoop/pom.xml b/cat-hadoop/pom.xml index 5162d7bf94..e02794d7b5 100644 --- a/cat-hadoop/pom.xml +++ b/cat-hadoop/pom.xml @@ -34,16 +34,28 @@ - - com.dianping.cat - cat-core - - - org.xerial.snappy - snappy-java - - - + + com.dianping.cat + cat-core + + + io.netty + netty-all + + + org.xerial.snappy + snappy-java + + + org.apache.commons + commons-lang3 + + + commons-io + commons-io + + + - - - - org.apache.maven.surefire - surefire-junit47 - 2.9 - - - - - maven-eclipse-plugin - 2.9 - - true - none - - - .settings/org.eclipse.jdt.core.prefs - - - - .settings/org.eclipse.core.resources.prefs - - =UTF-8 - ]]> - - - - - - - org.unidal.maven.plugins - codegen-maven-plugin - 2.5.9 - - - org.unidal.maven.plugins - plexus-maven-plugin - 2.5.9 - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.8 - true - - ossrh - https://s01.oss.sonatype.org/ - ${deploy.autoRelease} - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 - - - attach-javadocs - - jar - - - -Xdoclint:none - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.2 - - 1.8 - 1.8 - - - - - - - org.apache.maven.plugins - maven-source-plugin - - - org.apache.maven.plugins - maven-javadoc-plugin - - - org.apache.maven.plugins - maven-compiler-plugin - - - - - - central - Maven2 Central Repository - default - https://repo1.maven.org/maven2 - - - unidal.releases - http://unidal.org/nexus/content/repositories/releases/ - - - - - central - https://repo1.maven.org/maven2 - - - unidal.releases - http://unidal.org/nexus/content/repositories/releases/ - - - - utf-8 - false - - - - ossrh - OSS Snapshots Repository - https://s01.oss.sonatype.org/content/repositories/snapshots/ - - - ossrh - OSS Staging Repository - https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ - - - + + + 4.0.0 + com.dianping.cat + parent + 4.0-RC1 + parent + Central Application Tracking + pom + https://github.com/dianping/cat + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo,manual + + + + + meituan + tech@meituan.com + meituan + https://github.com/dianping + + + + scm:git:https://github.com/dianping/cat.git + scm:git:https://github.com/dianping/cat.git + https://github.com/dianping/cat + ${project.version} + + + cat-client + cat-core + cat-consumer + cat-hadoop + cat-home + cat-alarm + cat-boot + + + + + com.dianping.cat + cat-client + ${project.version} + + + com.dianping.cat + cat-core + ${project.version} + + + com.dianping.cat + cat-hadoop + ${project.version} + + + com.dianping.cat + cat-consumer + ${project.version} + + + com.dianping.cat + cat-alarm + ${project.version} + + + com.dianping.cat + cat-home + ${project.version} + war + + + org.unidal.framework + web-framework + 3.0.3 + + + org.unidal.webres + WebResServer + 1.2.1 + + + junit + junit + 4.13.2 + + + org.mortbay.jetty + jetty + 6.1.26 + + + org.mortbay.jetty + jetty-util + 6.1.26 + + + org.mortbay.jetty + jsp-api-2.1 + 6.1.14 + provided + + + org.mortbay.jetty + jsp-2.1 + 6.1.14 + + + javax.servlet + jstl + 1.2 + + + javax.servlet + servlet-api + 2.5 + + + javax.servlet.jsp + jsp-api + 2.1 + + + jakarta.annotation + jakarta.annotation-api + 3.0.0 + + + com.mysql + mysql-connector-j + 9.7.0 + + + org.apache.hadoop + hadoop-client + 2.4.1 + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + + + + + io.netty + netty-all + 4.1.128.Final + + + com.google.code.gson + gson + 2.13.2 + + + org.apache.httpcomponents + httpclient + 4.5.14 + + + org.apache.httpcomponents + httpmime + 4.5.14 + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson2.version} + + + org.mybatis + mybatis + ${mybatis.version} + + + org.mybatis + mybatis-spring + ${mybatis-spring.version} + + + org.springframework + spring-context + ${spring-framework.version} + + + org.springframework + spring-web + ${spring-framework.version} + + + org.springframework + spring-jdbc + ${spring-framework.version} + + + org.springframework + spring-tx + ${spring-framework.version} + + + commons-codec + commons-codec + 1.19.0 + + + commons-lang + commons-lang + 2.6 + + + org.apache.commons + commons-lang3 + 3.20.0 + + + commons-io + commons-io + 2.22.0 + + + com.google.guava + guava + 33.6.0-jre + + + org.xerial.snappy + snappy-java + 1.1.10.8 + + + log4j + log4j + 1.2.14 + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${slf4j.version} + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.freemarker + freemarker + 2.3.34 + + + com.mchange + c3p0 + 0.11.2 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + + ossrh + + + + org.apache.maven.plugins + maven-gpg-plugin + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + + + + github-action + + + + org.apache.maven.plugins + maven-gpg-plugin + + + --pinentry-mode + loopback + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + + + + + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/AllTests.java + + + + + + org.apache.maven.surefire + surefire-junit47 + ${maven-surefire-plugin.version} + + + + + maven-eclipse-plugin + 2.9 + + true + none + + + .settings/org.eclipse.jdt.core.prefs + + + + .settings/org.eclipse.core.resources.prefs + + =UTF-8 + ]]> + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + ossrh + https://s01.oss.sonatype.org/ + ${deploy.autoRelease} + + + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven-javadoc-plugin.version} + + + attach-javadocs + + jar + + + none + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.release} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + org.apache.maven.plugins + maven-resources-plugin + ${maven-resources-plugin.version} + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + org.apache.maven.plugins + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + org.apache.maven.plugins + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + + + + org.apache.maven.plugins + maven-antrun-plugin + false + + + ban-unidal-lookup-annotations + validate + + run + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-build-environment + + enforce + + + + + [21,22) + + + [3.9.0,) + + + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + central + Maven2 Central Repository + default + https://repo1.maven.org/maven2 + + + unidal.releases + http://unidal.org/nexus/content/repositories/releases/ + + + + + central + https://repo1.maven.org/maven2 + + + unidal.releases + http://unidal.org/nexus/content/repositories/releases/ + + + + utf-8 + 21 + 3.14.1 + 3.5.6 + 3.5.1 + 3.3.1 + 3.6.2 + 3.3.1 + 3.12.0 + 3.6.2 + 3.1.0 + 2.0.17 + 1.5.34 + 2.0.62 + 3.5.19 + 4.0.0 + 1.18.46 + 4.1.0 + 7.0.3 + 9.0.112 + false + + + + ossrh + OSS Snapshots Repository + https://s01.oss.sonatype.org/content/repositories/snapshots/ + + + ossrh + OSS Staging Repository + https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ + + + diff --git a/script/CatApplication.sql b/script/CatApplication.sql index 987d2f589c..006d2ff7c8 100644 --- a/script/CatApplication.sql +++ b/script/CatApplication.sql @@ -1,305 +1,440 @@ -CREATE TABLE `dailyreport` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL COMMENT '报表名称, transaction, problem...', - `ip` varchar(50) NOT NULL COMMENT '报表来自于哪台cat-consumer机器', - `domain` varchar(50) NOT NULL COMMENT '报表处理的Domain信息', - `period` datetime NOT NULL COMMENT '报表时间段', - `type` tinyint(4) NOT NULL COMMENT '报表数据格式, 1/xml, 2/json, 默认1', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - UNIQUE KEY `period` (`period`,`domain`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='天报表'; +CREATE TABLE `t_daily_report` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称, transaction, problem...', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '报表来自于哪台cat-consumer机器', + `domain` varchar(50) NOT NULL DEFAULT '' COMMENT '报表处理的Domain信息', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '报表数据格式, 1/xml, 2/json, 默认1', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_period_domain_name` (`period`,`domain`,`name`), + KEY `idx_domain_name` (`domain`,`name`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='天报表'; -CREATE TABLE `weeklyreport` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL COMMENT '报表名称, transaction, problem...', - `ip` varchar(50) NOT NULL COMMENT '报表来自于哪台cat-consumer机器', - `domain` varchar(50) NOT NULL COMMENT '报表处理的Domain信息', - `period` datetime NOT NULL COMMENT '报表时间段', - `type` tinyint(4) NOT NULL COMMENT '报表数据格式, 1/xml, 2/json, 默认1', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - UNIQUE KEY `period` (`period`,`domain`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='周报表'; +CREATE TABLE `t_weekly_report` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称, transaction, problem...', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '报表来自于哪台cat-consumer机器', + `domain` varchar(50) NOT NULL DEFAULT '' COMMENT '报表处理的Domain信息', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '报表数据格式, 1/xml, 2/json, 默认1', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_period_domain_name` (`period`,`domain`,`name`), + KEY `idx_domain_name` (`domain`,`name`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='周报表'; -CREATE TABLE `monthreport` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL COMMENT '报表名称, transaction, problem...', - `ip` varchar(50) NOT NULL COMMENT '报表来自于哪台cat-consumer机器', - `domain` varchar(50) NOT NULL COMMENT '报表处理的Domain信息', - `period` datetime NOT NULL COMMENT '报表时间段', - `type` tinyint(4) NOT NULL COMMENT '报表数据格式, 1/xml, 2/json, 默认1', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - UNIQUE KEY `period` (`period`,`domain`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='月报表'; +CREATE TABLE `t_monthly_report` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称, transaction, problem...', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '报表来自于哪台cat-consumer机器', + `domain` varchar(50) NOT NULL DEFAULT '' COMMENT '报表处理的Domain信息', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '报表数据格式, 1/xml, 2/json, 默认1', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_period_domain_name` (`period`,`domain`,`name`), + KEY `idx_domain_name` (`domain`,`name`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='月报表'; -CREATE TABLE `hostinfo` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `ip` varchar(50) NOT NULL COMMENT '部署机器IP', - `domain` varchar(200) NOT NULL COMMENT '部署机器对应的项目名', - `hostname` varchar(200) DEFAULT NULL COMMENT '机器域名', - `creation_date` datetime NOT NULL, - `last_modified_date` datetime NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `ip_index` (`ip`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='IP和项目名的对应关系'; +CREATE TABLE `t_host_info` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '部署机器IP', + `domain` varchar(200) NOT NULL DEFAULT '' COMMENT '部署机器对应的项目名', + `hostname` varchar(200) NOT NULL DEFAULT '' COMMENT '机器域名', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_ip` (`ip`), + KEY `idx_domain` (`domain`), + KEY `idx_hostname` (`hostname`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='IP和项目名的对应关系'; -CREATE TABLE `hourlyreport` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `type` tinyint(4) NOT NULL COMMENT '报表类型, 1/xml, 9/binary 默认1', - `name` varchar(20) NOT NULL COMMENT '报表名称', - `ip` varchar(50) DEFAULT NULL COMMENT '报表来自于哪台机器', - `domain` varchar(50) NOT NULL COMMENT '报表项目', - `period` datetime NOT NULL COMMENT '报表时间段', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - KEY `IX_Domain_Name_Period` (`domain`,`name`,`period`), - KEY `IX_Name_Period` (`name`,`period`), - KEY `IX_Period` (`period`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='用于存放实时报表信息,处理之后的结果'; +CREATE TABLE `t_hourly_report` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '报表类型, 1/xml, 9/binary, 默认1', + `name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '报表来自于哪台机器', + `domain` varchar(50) NOT NULL DEFAULT '' COMMENT '报表项目', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_domain_name_period` (`domain`,`name`,`period`), + KEY `idx_name_period` (`name`,`period`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='小时报表'; -CREATE TABLE `hourly_report_content` ( - `report_id` int(11) NOT NULL COMMENT '报表ID', - `content` longblob NOT NULL COMMENT '二进制报表内容', - `period` datetime NOT NULL COMMENT '报表时间段', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`report_id`), - KEY `IX_Period` (`period`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='小时报表二进制内容'; +CREATE TABLE `t_hourly_report_content` +( + `report_id` bigint NOT NULL COMMENT '报表ID', + `content` longblob NOT NULL COMMENT '二进制报表内容', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`report_id`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='小时报表二进制内容'; -CREATE TABLE `daily_report_content` ( - `report_id` int(11) NOT NULL COMMENT '报表ID', - `content` longblob NOT NULL COMMENT '二进制报表内容', - `period` datetime COMMENT '报表时间段', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`report_id`), - KEY `IX_Period` (`period`) -)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='天报表二进制内容'; +CREATE TABLE `t_daily_report_content` +( + `report_id` bigint NOT NULL COMMENT '报表ID', + `content` longblob NOT NULL COMMENT '二进制报表内容', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`report_id`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='天报表二进制内容'; -CREATE TABLE `weekly_report_content` ( - `report_id` int(11) NOT NULL COMMENT '报表ID', - `content` longblob NOT NULL COMMENT '二进制报表内容', - `period` datetime COMMENT '报表时间段', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`report_id`), - KEY `IX_Period` (`period`) -)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='周报表二进制内容'; +CREATE TABLE `t_weekly_report_content` +( + `report_id` bigint NOT NULL COMMENT '报表ID', + `content` longblob NOT NULL COMMENT '二进制报表内容', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`report_id`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='周报表二进制内容'; -CREATE TABLE `monthly_report_content` ( - `report_id` int(11) NOT NULL COMMENT '报表ID', - `content` longblob NOT NULL COMMENT '二进制报表内容', - `period` datetime COMMENT '报表时间段', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`report_id`), - KEY `IX_Period` (`period`) -)ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='月报表二进制内容'; +CREATE TABLE `t_monthly_report_content` +( + `report_id` bigint NOT NULL COMMENT '报表ID', + `content` longblob NOT NULL COMMENT '二进制报表内容', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`report_id`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='月报表二进制内容'; -CREATE TABLE `businessReport` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `type` tinyint(4) NOT NULL COMMENT '报表类型 报表数据格式, 1/Binary, 2/xml , 3/json', - `name` varchar(20) NOT NULL COMMENT '报表名称', - `ip` varchar(50) NOT NULL COMMENT '报表来自于哪台机器', - `productLine` varchar(50) NOT NULL COMMENT '指标来源于哪个产品组', - `period` datetime NOT NULL COMMENT '报表时间段', - `content` longblob COMMENT '用于存放报表的具体内容', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - KEY `IX_Period_productLine_name` (`period`,`productLine`,`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED COMMENT='用于存放业务监控实时报表信息,处理之后的结果'; +CREATE TABLE `t_business_report` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '报表数据格式, 1/binary, 2/xml, 3/json', + `name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '报表来源机器IP', + `product_line` varchar(50) NOT NULL DEFAULT '' COMMENT '业务指标来源产品线', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间段', + `content` longblob NOT NULL COMMENT '业务报表内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_period_product_line_name` (`period`,`product_line`,`name`), + KEY `idx_product_line_name_period` (`product_line`,`name`,`period`), + KEY `idx_period` (`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='业务监控实时报表'; -CREATE TABLE `task` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `producer` varchar(20) NOT NULL COMMENT '任务创建者ip', - `consumer` varchar(20) NULL COMMENT '任务执行者ip', - `failure_count` tinyint(4) NOT NULL COMMENT '任务失败次数', - `report_name` varchar(20) NOT NULL COMMENT '报表名称, transaction, problem...', - `report_domain` varchar(50) NOT NULL COMMENT '报表处理的Domain信息', - `report_period` datetime NOT NULL COMMENT '报表时间', - `status` tinyint(4) NOT NULL COMMENT '执行状态: 1/todo, 2/doing, 3/done 4/failed', - `task_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0表示小时任务,1表示天任务', - `creation_date` datetime NOT NULL COMMENT '任务创建时间', - `start_date` datetime NULL COMMENT '开始时间, 这次执行开始时间', - `end_date` datetime NULL COMMENT '结束时间, 这次执行结束时间', - PRIMARY KEY (`id`), - UNIQUE KEY `task_period_domain_name_type` (`report_period`,`report_domain`,`report_name`,`task_type`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台任务'; +CREATE TABLE `t_task` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `producer` varchar(50) NOT NULL DEFAULT '' COMMENT '任务创建机器IP', + `consumer` varchar(50) NOT NULL DEFAULT '' COMMENT '任务执行机器IP', + `failure_count` int NOT NULL DEFAULT '0' COMMENT '任务失败次数', + `report_name` varchar(20) NOT NULL DEFAULT '' COMMENT '报表名称, transaction, problem...', + `report_domain` varchar(50) NOT NULL DEFAULT '' COMMENT '报表所属Domain', + `report_period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '报表时间', + `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '执行状态, 1/todo, 2/doing, 3/done, 4/failed', + `task_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '任务类型, 0/hourly, 1/daily', + `start_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '执行开始时间', + `end_time` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '执行结束时间', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_report_period_domain_name_type` (`report_period`,`report_domain`,`report_name`,`task_type`), + KEY `idx_status_consumer` (`status`,`consumer`), + KEY `idx_report_period` (`report_period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='后台任务'; -CREATE TABLE `project` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `domain` varchar(200) NOT NULL COMMENT '项目名称', - `cmdb_domain` varchar(200) DEFAULT NULL COMMENT 'cmdb项目名称', - `level` int(5) DEFAULT NULL COMMENT '项目级别', - `bu` varchar(50) DEFAULT NULL COMMENT 'CMDB事业部', - `cmdb_productline` varchar(50) DEFAULT NULL COMMENT 'CMDB产品线', - `owner` varchar(50) DEFAULT NULL COMMENT '项目负责人', - `email` longtext DEFAULT NULL COMMENT '项目组邮件', - `phone` longtext DEFAULT NULL COMMENT '联系电话', - `creation_date` datetime DEFAULT NULL COMMENT '创建时间', - `modify_date` datetime DEFAULT NULL COMMENT '修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `domain` (`domain`) -)ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='项目基本信息'; -CREATE TABLE `topologyGraph` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `ip` varchar(50) NOT NULL COMMENT '报表来自于哪台cat-client机器ip', - `period` datetime NOT NULL COMMENT '报表时间段,精确到分钟', - `type` tinyint(4) NOT NULL COMMENT '报表数据格式, 1/xml, 2/json, 3/binary', - `content` longblob COMMENT '用于存放报表的具体内容', - `creation_date` datetime NOT NULL COMMENT '报表创建时间', - PRIMARY KEY (`id`), - KEY `period` (`period`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用于存储历史的拓扑图曲线'; +CREATE TABLE `t_project` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `domain` varchar(200) NOT NULL DEFAULT '' COMMENT '项目名称', + `cmdb_domain` varchar(200) NOT NULL DEFAULT '' COMMENT 'CMDB项目名称', + `level` int NOT NULL DEFAULT '0' COMMENT '项目级别', + `bu` varchar(50) NOT NULL DEFAULT '' COMMENT 'CMDB事业部', + `cmdb_product_line` varchar(50) NOT NULL DEFAULT '' COMMENT 'CMDB产品线', + `owner` varchar(50) NOT NULL DEFAULT '' COMMENT '项目负责人', + `email` text NOT NULL COMMENT '项目组邮箱', + `phone` text NOT NULL COMMENT '联系电话', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_domain` (`domain`), + KEY `idx_cmdb_domain` (`cmdb_domain`), + KEY `idx_cmdb_product_line` (`cmdb_product_line`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='项目基础信息'; -CREATE TABLE `config` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL COMMENT '配置名称', - `content` longtext COMMENT '配置的具体内容', - `creation_date` datetime NOT NULL COMMENT '配置创建时间', - `modify_date` datetime NOT NULL COMMENT '配置修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用于存储系统的全局配置信息'; -CREATE TABLE `baseline` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `report_name` varchar(100) DEFAULT NULL, - `index_key` varchar(100) DEFAULT NULL, - `report_period` datetime DEFAULT NULL, - `data` blob, - `creation_date` datetime DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `period_name_key` (`report_period`,`report_name`,`index_key`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `t_topology_graph` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `ip` varchar(50) NOT NULL DEFAULT '' COMMENT '生成拓扑图的机器IP', + `period` datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '拓扑图时间段, 精确到分钟', + `type` tinyint(4) NOT NULL DEFAULT '3' COMMENT '数据格式, 1/xml, 2/json, 3/binary', + `content` longblob NOT NULL COMMENT '拓扑图内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_period` (`period`), + KEY `idx_ip_period` (`ip`,`period`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED COMMENT='历史拓扑图'; -CREATE TABLE `alteration` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `type` varchar(64) NOT NULL COMMENT '分类', - `title` varchar(128) NOT NULL COMMENT '变更标题', - `domain` varchar(128) NOT NULL COMMENT '变更项目', - `hostname` varchar(128) NOT NULL COMMENT '变更机器名', - `ip` varchar(128) DEFAULT NULL COMMENT '变更机器IP', - `date` datetime NOT NULL COMMENT '变更时间', - `user` varchar(45) NOT NULL COMMENT '变更用户', - `alt_group` varchar(45) DEFAULT NULL COMMENT '变更组别', - `content` longtext NOT NULL COMMENT '变更内容', - `url` varchar(200) DEFAULT NULL COMMENT '变更链接', - `status` tinyint(4) DEFAULT '0' COMMENT '变更状态', - `creation_date` datetime NOT NULL COMMENT '数据库创建时间', - PRIMARY KEY (`id`), - KEY `ind_date_domain_host` (`date`,`domain`,`hostname`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='变更表'; -CREATE TABLE `alert` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `domain` varchar(128) NOT NULL COMMENT '告警项目', - `alert_time` datetime NOT NULL COMMENT '告警时间', - `category` varchar(64) NOT NULL COMMENT '告警分类:network/business/system/exception -alert', - `type` varchar(64) NOT NULL COMMENT '告警类型:error/warning', - `content` longtext NOT NULL COMMENT '告警内容', - `metric` varchar(128) NOT NULL COMMENT '告警指标', - `creation_date` datetime NOT NULL COMMENT '数据插入时间', - PRIMARY KEY (`id`), - KEY `idx_alert_time_category_domain` (`alert_time`,`category`,`domain`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储告警信息'; +CREATE TABLE `t_config` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(100) NOT NULL DEFAULT '' COMMENT '配置名称', + `content` longtext NOT NULL COMMENT '配置内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name` (`name`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统全局配置'; -CREATE TABLE `alert_summary` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `domain` varchar(128) NOT NULL COMMENT '告警项目', - `alert_time` datetime NOT NULL COMMENT '告警时间', - `content` longtext NOT NULL COMMENT '统一告警内容', - `creation_date` datetime NOT NULL COMMENT '数据插入时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='统一告警信息'; +CREATE TABLE `t_baseline` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `report_name` varchar(100) NOT NULL DEFAULT '' COMMENT '报表名称', + `index_key` varchar(255) NOT NULL DEFAULT '' COMMENT '指标Key', + `report_period` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表时间', + `data` blob NOT NULL COMMENT '基线数据', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_period_name_key` (`report_period`, `report_name`, `index_key`), + KEY `idx_report_name` (`report_name`), + KEY `idx_index_key` (`index_key`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='指标基线数据'; -CREATE TABLE `operation` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `user` varchar(128) NOT NULL COMMENT '用户名', - `module` varchar(128) NOT NULL COMMENT '模块', - `operation` varchar(128) NOT NULL COMMENT '操作', - `time` datetime NOT NULL COMMENT '修改时间', - `content` longtext NOT NULL COMMENT '修改内容', - `creation_date` datetime NOT NULL COMMENT '数据插入时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户操作日志'; +CREATE TABLE `t_alteration` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `type` varchar(64) NOT NULL DEFAULT '' COMMENT '变更分类', + `title` varchar(128) NOT NULL DEFAULT '' COMMENT '变更标题', + `domain` varchar(128) NOT NULL DEFAULT '' COMMENT '变更项目', + `hostname` varchar(128) NOT NULL DEFAULT '' COMMENT '变更机器名', + `ip` varchar(128) NOT NULL DEFAULT '' COMMENT '变更机器IP', + `change_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '变更时间', + `user` varchar(64) NOT NULL DEFAULT '' COMMENT '变更用户', + `alt_group` varchar(64) NOT NULL DEFAULT '' COMMENT '变更组别', + `content` longtext NOT NULL COMMENT '变更内容', + `url` varchar(512) NOT NULL DEFAULT '' COMMENT '变更链接', + `status` tinyint NOT NULL DEFAULT '0' COMMENT '变更状态', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `ind_date_domain_host` (`change_time`, `domain`, `hostname`), + KEY `idx_type_change_time` (`type`, `change_time`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='变更记录'; -CREATE TABLE `overload` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `report_id` int(11) NOT NULL COMMENT '报告id', - `report_type` tinyint(4) NOT NULL COMMENT '报告类型 1:hourly 2:daily 3:weekly 4:monthly', - `report_size` double NOT NULL COMMENT '报告大小 单位MB', - `period` datetime NOT NULL COMMENT '报表时间', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`id`), - KEY `period` (`period`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='过大容量表'; +CREATE TABLE `t_alert` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `domain` varchar(128) NOT NULL DEFAULT '' COMMENT '告警项目', + `alert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '告警时间', + `category` varchar(64) NOT NULL DEFAULT '' COMMENT '告警分类', + `type` varchar(64) NOT NULL DEFAULT '' COMMENT '告警类型', + `content` longtext NOT NULL COMMENT '告警内容', + `metric` varchar(256) NOT NULL DEFAULT '' COMMENT '告警指标', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_alert_time_category_domain` (`alert_time`, `category`, `domain`), + KEY `idx_domain_alert_time` (`domain`, `alert_time`), + KEY `idx_category_alert_time` (`category`, `alert_time`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='告警记录'; -CREATE TABLE `config_modification` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `user_name` varchar(64) NOT NULL COMMENT '用户名', - `account_name` varchar(64) NOT NULL COMMENT '账户名', - `action_name` varchar(64) NOT NULL COMMENT 'action名', - `argument` longtext COMMENT '参数内容', - `date` datetime NOT NULL COMMENT '修改时间', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='配置修改记录表'; +CREATE TABLE `t_alert_summary` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `domain` varchar(128) NOT NULL DEFAULT '' COMMENT '告警项目', + `alert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '告警时间', + `content` longtext NOT NULL COMMENT '统一告警内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_alert_time_domain` (`alert_time`, `domain`), + KEY `idx_domain_alert_time` (`domain`, `alert_time`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='统一告警信息'; -CREATE TABLE `user_define_rule` ( - `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增长ID', - `content` text NOT NULL COMMENT '用户定义规则', - `creation_date` datetime NOT NULL COMMENT '创建时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户定义规则表'; +CREATE TABLE `t_operation` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user` varchar(128) NOT NULL DEFAULT '' COMMENT '用户名', + `module` varchar(128) NOT NULL DEFAULT '' COMMENT '模块', + `operation` varchar(128) NOT NULL DEFAULT '' COMMENT '操作', + `operation_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '操作时间', + `content` longtext NOT NULL COMMENT '操作内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_operation_time` (`operation_time`), + KEY `idx_user_operation_time` (`user`, `operation_time`), + KEY `idx_module_operation_time` (`module`, `operation_time`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户操作日志'; -CREATE TABLE `business_config` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(20) NOT NULL DEFAULT '' COMMENT '配置名称', - `domain` varchar(50) NOT NULL DEFAULT '' COMMENT '项目', - `content` longtext COMMENT '配置内容', - `updatetime` datetime NOT NULL, - PRIMARY KEY (`id`), - KEY `updatetime` (`updatetime`), - KEY `name_domain` (`name`,`domain`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `t_overload` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `report_id` bigint NOT NULL DEFAULT '0' COMMENT '报表ID', + `report_type` tinyint NOT NULL DEFAULT '0' COMMENT '报表类型 1=hourly 2=daily 3=weekly 4=monthly', + `report_size` double NOT NULL DEFAULT '0' COMMENT '报表大小,单位MB', + `period` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '报表时间', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_period` (`period`), + KEY `idx_report_type_report_id` (`report_type`, `report_id`), + KEY `idx_period_report_type` (`period`, `report_type`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='过大容量报表'; -CREATE TABLE `metric_screen` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(50) NOT NULL COMMENT '配置名称', - `graph_name` varchar(50) NOT NULL DEFAULT '' COMMENT 'Graph名称', - `view` varchar(50) NOT NULL DEFAULT '' COMMENT '视角', - `endPoints` longtext NOT NULL, - `measurements` longtext NOT NULL COMMENT '配置的指标', - `content` longtext NOT NULL COMMENT '配置的具体内容', - `creation_date` datetime NOT NULL COMMENT '配置创建时间', - `updatetime` datetime NOT NULL COMMENT '配置修改时间', - PRIMARY KEY (`id`), - UNIQUE KEY `name_graph` (`name`,`graph_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统监控的screen配置'; +CREATE TABLE `t_config_modification` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_name` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名', + `account_name` varchar(64) NOT NULL DEFAULT '' COMMENT '账号名', + `action_name` varchar(64) NOT NULL DEFAULT '' COMMENT '操作名称', + `argument` longtext NOT NULL COMMENT '参数内容', + `modify_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_modify_time` (`modify_time`), + KEY `idx_user_modify_time` (`user_name`, `modify_time`), + KEY `idx_account_modify_time` (`account_name`, `modify_time`), + KEY `idx_action_modify_time` (`action_name`, `modify_time`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置修改记录'; -CREATE TABLE `metric_graph` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `graph_id` int(11) NOT NULL COMMENT '大盘ID', - `name` varchar(50) NOT NULL COMMENT '配置ID', - `content` longtext COMMENT '配置的具体内容', - `creation_date` datetime NOT NULL COMMENT '配置创建时间', - `updatetime` datetime NOT NULL COMMENT '配置修改时间', - PRIMARY KEY (`id`), - UNIQUE `name` (`name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统监控的graph配置'; +CREATE TABLE `t_user_define_rule` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `content` text NOT NULL COMMENT '用户自定义规则', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户自定义规则'; -CREATE TABLE `server_alarm_rule` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `category` varchar(50) NOT NULL COMMENT '监控分类', - `endPoint` varchar(200) NOT NULL COMMENT '监控对象ID', - `measurement` varchar(200) NOT NULL COMMENT '监控指标', - `tags` varchar(200) NOT NULL DEFAULT '' COMMENT '监控指标标签', - `content` longtext NOT NULL COMMENT '配置的具体内容', - `type` varchar(20) NOT NULL DEFAULT '' COMMENT '数据聚合方式', - `creator` varchar(100) DEFAULT '' COMMENT '创建人', - `creation_date` datetime NOT NULL COMMENT '配置创建时间', - `updatetime` datetime NOT NULL COMMENT '配置修改时间', - PRIMARY KEY (`id`), - KEY `updatetime` (`updatetime`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='系统告警的配置'; +CREATE TABLE `t_business_config` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(64) NOT NULL DEFAULT '' COMMENT '配置名称', + `domain` varchar(128) NOT NULL DEFAULT '' COMMENT '项目', + `content` longtext NOT NULL COMMENT '配置内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name_domain` (`name`, `domain`), + KEY `idx_name` (`name`), + KEY `idx_domain` (`domain`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='业务配置'; + +CREATE TABLE `t_metric_screen` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `name` varchar(64) NOT NULL DEFAULT '' COMMENT '配置名称', + `graph_name` varchar(64) NOT NULL DEFAULT '' COMMENT 'Graph名称', + `view` varchar(64) NOT NULL DEFAULT '' COMMENT '视角', + `end_points` longtext NOT NULL COMMENT '端点配置', + `measurements` longtext NOT NULL COMMENT '指标配置', + `content` longtext NOT NULL COMMENT '配置内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name_graph` (`name`, `graph_name`), + KEY `idx_name` (`name`), + KEY `idx_graph_name` (`graph_name`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统监控Screen配置'; + +CREATE TABLE `t_metric_graph` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `graph_id` bigint NOT NULL DEFAULT '0' COMMENT '大盘ID', + `name` varchar(64) NOT NULL DEFAULT '' COMMENT '配置ID', + `content` longtext NOT NULL COMMENT '配置内容', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name` (`name`), + KEY `idx_graph_id` (`graph_id`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统监控Graph配置'; + +CREATE TABLE `t_server_alarm_rule` +( + `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `category` varchar(64) NOT NULL DEFAULT '' COMMENT '监控分类', + `endpoint` varchar(256) NOT NULL DEFAULT '' COMMENT '监控对象ID', + `measurement` varchar(256) NOT NULL DEFAULT '' COMMENT '监控指标', + `tags` varchar(512) NOT NULL DEFAULT '' COMMENT '监控指标标签', + `content` longtext NOT NULL COMMENT '配置内容', + `type` varchar(32) NOT NULL DEFAULT '' COMMENT '数据聚合方式', + `creator` varchar(128) NOT NULL DEFAULT '' COMMENT '创建人', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_category` (`category`), + KEY `idx_type` (`type`), + KEY `idx_category_type` (`category`,`type`), + KEY `idx_create_time` (`create_time`), + KEY `idx_update_time` (`update_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统告警规则配置'; diff --git a/script/install_maven.cmd b/script/install_maven.cmd new file mode 100644 index 0000000000..a5ce1929e5 --- /dev/null +++ b/script/install_maven.cmd @@ -0,0 +1,3 @@ +mvn install:install-file ` + -Dfile=D:\workspace\cat\cat-client\target\cat-client-4.0-RC1.jar ` + -DpomFile=D:\workspace\cat\cat-client\target\pom.xml \ No newline at end of file diff --git a/script/install_maven.sh b/script/install_maven.sh new file mode 100644 index 0000000000..f3df4d07a3 --- /dev/null +++ b/script/install_maven.sh @@ -0,0 +1,3 @@ +mvn install:install-file ^ + -Dfile=D:\workspace\cat\cat-client\target\cat-client-4.0-RC1.jar ^ + -DpomFile=D:\workspace\cat\cat-client\target\pom.xml \ No newline at end of file