diff --git a/README.md b/README.md index a031069a..6f5822a6 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,116 @@ # UAVStack -UAVStack是智能化服务技术栈,是研发运维一体化的解决方案。UAV是无人机的缩写,寓意无人机翱翔蓝天,智能的,透明的完成任务。 -它包括任务机器人(代号HIT),全维监控(代号UAV.Monitor),应用性能管理(代号UAV.APM),服务治理(代号UAV.ServiceGovern),微服务计算(代号UAV.MSCP),用户体验管理(代号UAV.UEM)等。 +中文版README请点击(https://github.com/uavorg/uavstack/blob/master/README%E4%B8%AD%E6%96%87%E7%89%88.md) -UAVStack is an intelligent service technology stack. It is a solution for integration of R & D, operation and maintenance. UAV is the abbreviation of unmanned aerial vehicle (UAV), which means that unmanned aerial vehicle flies into the sky, and completes tasks intelligently and transparently. +UAVStack as an intelligent service technology stack is the integrated solution to R&D, operation and maintenance. As the acronym of unmanned aerial vehicle, UAV depicts the scenario where the unmanned aerial vehicle hovers under the sky and completes tasks in an intelligent and transparent manner. This stack features AIOps Robot (HIT), full dimension monitoring (UAV.Monitor), application performance management (UAV.APM), service governance (UAV.ServiceGovern), micro-service computing (UAV.MSCP), user experience management (UAV.UEM), etc.. -It includes AIOps Robot (HIT),full dimension monitoring (UAV.Monitor), application performance management (UAV.APM), service governance (UAV.ServiceGovern), micro-service computing (UAV.MSCP), user experience management (UAV.UEM) etc.. - - -目前UAVStack开源系列 ( 官方网站:https://uavorg.github.io/main/ ) 包括 - -UAVStack Open Source series includes UAV.Monitor, UAV.APM, UAV.ServiceGovern, UAV.MSCP +Please visit https://uavorg.github.io/main/ for the open source series of UAVStack, including UAV.Monitor, UAV.APM, UAV.ServiceGovern and UAV.MSCP ![Uavstack开源系列](https://uavorg.github.io/main/index/img/support/openSource.png) -# 更新模式 Project Updating Principle -* 开源系列源代码Issue更新,将与内部版本完全同步,最低频率每周一次 -* 开源系列源代码相关的功能优化,将与内部版本完全同步,最低频率每周一次 -* 开源系列源代码相关的新功能开放,会提前一周预告,并于下周内发布 -* 标准部署包下载会与源代码更新同步,最低频率每周一次 -* AllInOne开发演示版原则上每月更新一次(打包上传比较耗时),中间更新请下载标准部署包替换 ---- -* The open source series updating is fully synchronized with the internal version, with the lowest frequency once a week -* The open source series related functional optimizations is fully synchronized with the internal version, with the lowest frequency once a week -* The open source series related new features will be announced a week ahead of schedule, and released next week -* The standard deployment pack download is synchronized with source code updates, with the lowest frequency once a week -* AllInOne pack are updated once a month (packaged, uploaded, and time-consuming) in principle, and you can download the standard deployment package instead +# Updating Rules +* Updates of the open source series (at least once a week) shall synchronize with those of the internal versions. +* Feature optimization of the open source series (at least once a week) shall synchronize with that of the internal versions as well. +* New features of the open source series shall be preannounced one week earlier and released within the following week. +* The standard deployment package shall synchronize with the updated source code (at least once a week). +* The AllInOne Demo Package is scheduled to be updated once a month. Please download the standard deployment package updated beyond the schedule. - -# 工程说明 Source Code Project Description -uavstack是UAVStack的All in One源代码仓库。 +# Project Description uavstack is the All in One source repository of UAVStack. -## 根POM -* com.creditease.uav.superpom 根POM,包含依赖管理,Build所需plugins等 (Parent POM for dependency management & build plugins) +## Parent POM +* com.creditease.uav.superpom: parent POM that support dependency management and build plugins ## UAV.Monitor -* com.creditease.uav.agent 监控代理程序MonitorAgent核心框架 (Core of MonitorAgent) -* com.creditease.uav.healthmanager Monitor核心服务,包括实时数据,画像数据存储/查询,实时报警流式计算,AppHub支持服务 (Core feature of HealthManager, including Monitoring Data Service,Application/Service Profiling,Real-time alarm streaming,AppHub Support Service) -* com.creditease.uav.notifycenter Monitor服务:报警中心服务端 (Notification Center Service) -* com.creditease.uav.monitorframework 探针MOF核心框架 (Core of JVM MonitorFramework for Tomcat,Jetty,SpringBoot,MSCP, etc...) -* com.creditease.uav.monitorframework.agent 探针MOF的javaagent实现 (JVM MonitorFramework javaagent support) -* com.creditease.uav.monitorframework.dproxy javaassit支持 (JVM MonitorFramework javassit support) -* com.creditease.uav.hook.* 探针MOF针对技术规范的钩子,包括Dubbo,HttpClients,JAXWS,JDBC,MongoClients,MQ,Redis等 (JVM MonitorFramework Hooks for application framework) -* com.creditease.uav.loghook 探针MOF针对log4j,logback支持 (JVM MonitorFramework Hook for log4j, logback) -* com.creditease.uav.tomcat.plus.core 探针MOF对Tomcat/SpringBoot的支持 (JVM MonitorFramework extension for Tomcat/SpringBoot) -* com.creditease.uav.jetty.plus.core 探针MOF对Jetty支持 (JVM MonitorFramework extension for Jetty) -* com.creditease.uav.mock.sl4j 去除某些框架依赖sl4j (mock sl4j) -* com.creditease.uav.ttl com.alibaba.ttl源代码引入 (Alibaba TTL) -* com.creditease.uav.monitorframework.buildFat WAR测试程序 (Function Test of JVM MonitorFramework) -* com.creditease.uav.monitorframework.springbootFat SpringBoot测试程序 (Function Test of JVM MonitorFramework for springboot) -* com.creditease.uav.agent.buildComponent 制作监控代理程序部署包 (Build POM for MonitorAgent) -* com.creditease.uav.healthmanager.buildComponent 制作健康管理程序部署包 (Build POM for HealthManager) -* com.creditease.uav.monitorframework.buildComponent 制作探针MOF部署包 (Build POM for JVM MonitorFramework) +* com.creditease.uav.agent: core of MonitorAgent +* com.creditease.uav.healthmanager: core features of HealthManager, including Monitoring Data Service,Application/Service Profiling,Real-time Alarm Streaming and AppHub Support Service +* com.creditease.uav.notifycenter: Notification Center Service +* com.creditease.uav.monitorframework: core of JVM MonitorFramework for Tomcat,Jetty,SpringBoot,MSCP, etc... +* com.creditease.uav.monitorframework.agent: JVM MonitorFramework javaagent support +* com.creditease.uav.monitorframework.dproxy: JVM MonitorFramework javassit support +* com.creditease.uav.hook.* : JVM MonitorFramework Hooks for application framework, including Dubbo, HttpClients, JAXWS, JDBC, MongoClients, MQ, Redis, etc. +* com.creditease.uav.loghook: JVM MonitorFramework Hook for log4j and logback +* com.creditease.uav.tomcat.plus.core: JVM MonitorFramework extension for Tomcat/SpringBoot +* com.creditease.uav.jetty.plus.core: JVM MonitorFramework extension for Jetty +* com.creditease.uav.mock.sl4j: mock sl4j +* com.creditease.uav.ttl: com.alibaba.ttl source code introduction (Alibaba TTL) +* com.creditease.uav.monitorframework.buildFat: function test of JVM MonitorFramework) +* com.creditease.uav.monitorframework.springbootFat: function test of JVM MonitorFramework for Springboot) +* com.creditease.uav.agent.buildComponent: build POM for MonitorAgent +* com.creditease.uav.healthmanager.buildComponent: build POM for HealthManager +* com.creditease.uav.monitorframework.buildComponent: build POM for JVM MonitorFramework ## UAV.APM -* com.creditease.uav.collect APM归集客户端/服务端 (Core of APM Data Collection Client & Service) -* com.creditease.uav.invokechain 调用链,日志服务存储和查询 (InvokeChain, Log Collection 2.0) -* com.creditease.uav.monitorframework.apm 探针MOF的APM支持 (JVM MonitorFramework extension for APM) -* com.creditease.uav.threadanalysis 一键式线程分析客户端和服务端 (One Shot Thread Analysis Client & Service) +* com.creditease.uav.collect: core of APM Data Collection client and server +* com.creditease.uav.invokechain: Invocation Chain and Log Collection 2.0 +* com.creditease.uav.monitorframework.apm: JVM MonitorFramework extension for APM +* com.creditease.uav.threadanalysis: one-click thread analysis client and server ## UAV.MSCP -* com.creditease.uav.base MSCP核心框架 (Core of MSCP) -* com.creditease.uav.agent.heartbeat 心跳客户端,心跳服务端,节点远程操控,进程扫描,进程值守 (Base feature of MSCP including heartbeat client & service,node remote opertaions,process auto scanning,process keep-alive support) -* com.creditease.uav.annoscan Fastclasspathscanner源代码引入,注解Class扫描 (Fastclasspathscanner) -* com.creditease.uav.cache.redis 基于Redis的CacheManager (Cache Framework based on redis) -* com.creditease.uav.dbaccess 存储管理器,目前封装了对MySql,OpenTSDB,HBase,MongoDB的存储和查询 (Data Store Framework for MySQL,OpenTSDB,HBase,MongoDB) -* com.creditease.uav.elasticsearch.client ElasticSearch的Shaded客户端封装,避免冲突 (ElasticSearch-Shaded-Client) -* com.creditease.uav.fastjson Fastjson源代码引入 (FastJson) -* com.creditease.uav.helper Util型支持类库 (Util Support Lib) -* com.creditease.uav.httpasync Http异步通信客户端,封装Apache AsyncClient (RPC Framework based on Apache Http AsyncClient) -* com.creditease.uav.logging MSCP日志支持 (MSCP Logging support) -* com.creditease.uav.messaging MSCP消息发送者和消费者支持,无需关心底层消息服务,依赖com.creditease.uav.mq (Messaging Service) -* com.creditease.uav.mq 消息队列服务底层封装,目前使用RocketMQ (Message Queue Support based on Rocket MQ) -* com.creditease.uav.notifymanager MSCP组件级报警支持 (MSCP Component level notification support) -* com.creditease.uav.upgrade MSCP升级客户端和服务端 (Remote upgrading support for MSCP) +* com.creditease.uav.base: core of MSCP +* com.creditease.uav.agent.heartbeat: basic features of MSCP, including heartbeat client & server,node remote control,process auto scanning and process keep-alive support +* com.creditease.uav.annoscan: Fastclasspathscanner source code introduction +* com.creditease.uav.cache.redis: Redis-based cache framework +* com.creditease.uav.dbaccess: data store framework for MySQL,OpenTSDB,HBase and MongoDB +* com.creditease.uav.elasticsearch.client: ElasticSearch-shaded-client to avoid conflicts +* com.creditease.uav.fastjson: Fastjson source code introduction +* com.creditease.uav.helper: Util support library +* com.creditease.uav.httpasync: Http asynchronous communication client based on Apache Http AsyncClient) +* com.creditease.uav.logging: MSCP logging support +* com.creditease.uav.messaging: MSCP messaging support that relies on com.creditease.uav.mq and requires no underlying messaging service +* com.creditease.uav.mq: message queue support based on Rocket MQ +* com.creditease.uav.notifymanager: component-level MSCP notification support +* com.creditease.uav.upgrade: remote upgrading support for MSCP client and server ## UAV.AppHub -* com.creditease.uav.console UAVStack交互前端,包括Monitor,APM等前端交互功能 (AppHub is the GUI console for UAVStack) -* com.creditease.uav.console.buildComponent 制作AppHub部署包 (Build POM for AppHub) +* com.creditease.uav.console: GUI console of UAVStack with front-end interactive features such as Monitor and APM +* com.creditease.uav.console.buildComponent: build POM for AppHub ## UAV.ServiceGovern -* 服务自动注册包含与探针MOF代码中 -* 服务发现代码包含与健康管理程序画像数据查询中 -* 服务降级保护(代码整理中,陆续更新...) -* 服务授权(代码整理中,陆续更新...) - -# 如何构建 How to Build -如果由于缺少jar包或某些依赖jar无法下载导致Maven Build Failure,可下载[参考Maven依赖仓库](https://pan.baidu.com/s/1gfeY8pH),使用该Maven仓库或将其复制到你正在使用的Maven仓库中。 +* Service automatic registration is included in the codes of MOF. +* Codes for service discovery is included in profile data query of HealthManager. +* Service downgrading protection (To be updated). +* Service authorization (To be update). -If you are unable to build because of the lack of jar packages or certain dependency jar, pleaser refer this [Maven Repository](https://pan.baidu.com/s/1gfeY8pH), use the Maven repository, or copy it to the Maven warehouse you are using. +# How to Build +Download the [reference Maven dependency repository](https://pan.baidu.com/s/1gfeY8pH)for Maven Build Failure resulted from the lack of jar packages or the lack of dependent jar packages, and use the downloaded Maven repository instead or copy it into the Maven repository that you are using. 1. build com.creditease.uav.superpom ``` cd com.creditease.uav.superpom mvn clean install ``` -2 中间件增强框架(MOF探针) +2 MonitorFramework ``` cd com.creditease.uav.monitorframework.buildComponent mvn clean install ``` -build结果 +build result >target > -build > -uavmof_1.0_XXXXX.zip > -uavmof_1.0_XXXXX.zip.MD5 -3. 监控代理程序(MA) +3. MonitorAgent ``` cd com.creditease.uav.agent.buildComponent mvn clean install ``` -build结果 +build result >target > -build > -uavagent_1.0_XXXXX.zip > -uavagent_1.0_XXXXX.zip.MD5 -4. 健康管理服务(HM) +4. HealthManager ``` cd com.creditease.uav.healthmanager.buildComponent mvn clean install ``` -build结果 +build result >target > -build > -uavhm_1.0_XXXXX.zip @@ -138,36 +122,30 @@ cd com.creditease.uav.console mvn clean install ``` -build结果 +build result >target > -com.creditease.uav.console-1.0.war -# 文档中心 Documents -## 全维监控UAV.Monitor+APM -* [用户指南](https://uavorg.github.io/documents/uavdoc_useroperation/index.html) -* [安装部署](https://uavorg.github.io/documents/uavdoc_deploydocs/index.html) -* [架构说明](https://uavorg.github.io/documents/uavdoc_architecture/index.html) - -# 下载中心 Downloads -## 全维监控UAV.Monitor+APM -* [MOF探针](https://pan.baidu.com/s/1cg4J0q) -* [监控代理程序](https://pan.baidu.com/s/1ge5MJ9h) -* [健康管理服务](https://pan.baidu.com/s/1i4HnV85) +# Documents +## UAV.Monitor+APM +* [User Operation](https://uavorg.github.io/documents/uavdoc_useroperation/index.html) +* [Deployment](https://uavorg.github.io/documents/uavdoc_deploydocs/index.html) +* [Architecture](https://uavorg.github.io/documents/uavdoc_architecture/index.html) + +# Downloads +## UAV.Monitor+APM +* [Monitor Framework](https://pan.baidu.com/s/1cg4J0q) +* [Monitor Agent](https://pan.baidu.com/s/1ge5MJ9h) +* [Health Manager](https://pan.baidu.com/s/1i4HnV85) * [AppHub](https://pan.baidu.com/s/1dFxtDZV) -## 第三方下载 Thirdparty Downloads +## Thirdparty Downloads * [rocket.war](https://pan.baidu.com/s/1dF6NeHN) -## AllInOne开发演示版 AllInOne Install Downloads -开发演示版的健康管理服务(HM)仅适合开发环境,演示环境,小规模测试环境。 -生产环境推荐使用[分布式部署](https://uavorg.github.io/main/uavdoc_deploydocs/healmanagerInstall/healmanagerInstall/microservice.html) +## AllInOne Installation Downloads +The Health Manager (HM) in the AllInOne Installation Package is applicable to development environments, demos and small-scale testing environments. +[A distributed deployment](https://uavorg.github.io/documents/uavdoc_deploydocs/healmanagerInstall/healmanagerInstall/microservice.html) is recommended for the production environment. -The health management service (HM) in AllInOne Install Package is only suitable for development environments, demos, and small scale testing environments. [A distributed deployment](https://uavorg.github.io/main/uavdoc_deploydocs/healmanagerInstall/healmanagerInstall/microservice.html) is recommended for the production environment - -* [Windows64位](https://pan.baidu.com/s/1jIF0wNs) +* [Windows64](https://pan.baidu.com/s/1jIF0wNs) * [Mac](https://pan.baidu.com/s/1mhCykp6) * [Linux(CentOS)](https://pan.baidu.com/s/1nvj6jW1) - - - - diff --git "a/README\344\270\255\346\226\207\347\211\210.md" "b/README\344\270\255\346\226\207\347\211\210.md" new file mode 100644 index 00000000..f6dcebe4 --- /dev/null +++ "b/README\344\270\255\346\226\207\347\211\210.md" @@ -0,0 +1,173 @@ +# UAVStack +UAVStack是智能化服务技术栈,是研发运维一体化的解决方案。UAV是无人机的缩写,寓意无人机翱翔蓝天,智能的,透明的完成任务。 +它包括任务机器人(代号HIT),全维监控(代号UAV.Monitor),应用性能管理(代号UAV.APM),服务治理(代号UAV.ServiceGovern),微服务计算(代号UAV.MSCP),用户体验管理(代号UAV.UEM)等。 + +UAVStack is an intelligent service technology stack. It is a solution for integration of R & D, operation and maintenance. UAV is the abbreviation of unmanned aerial vehicle (UAV), which means that unmanned aerial vehicle flies into the sky, and completes tasks intelligently and transparently. + +It includes AIOps Robot (HIT),full dimension monitoring (UAV.Monitor), application performance management (UAV.APM), service governance (UAV.ServiceGovern), micro-service computing (UAV.MSCP), user experience management (UAV.UEM) etc.. + + +目前UAVStack开源系列 ( 官方网站:https://uavorg.github.io/main/ ) 包括 + +UAVStack Open Source series includes UAV.Monitor, UAV.APM, UAV.ServiceGovern, UAV.MSCP + +![Uavstack开源系列](https://uavorg.github.io/main/index/img/support/openSource.png) + +# 更新模式 Project Updating Principle +* 开源系列源代码Issue更新,将与内部版本完全同步,最低频率每周一次 +* 开源系列源代码相关的功能优化,将与内部版本完全同步,最低频率每周一次 +* 开源系列源代码相关的新功能开放,会提前一周预告,并于下周内发布 +* 标准部署包下载会与源代码更新同步,最低频率每周一次 +* AllInOne开发演示版原则上每月更新一次(打包上传比较耗时),中间更新请下载标准部署包替换 +--- +* The open source series updating is fully synchronized with the internal version, with the lowest frequency once a week +* The open source series related functional optimizations is fully synchronized with the internal version, with the lowest frequency once a week +* The open source series related new features will be announced a week ahead of schedule, and released next week +* The standard deployment pack download is synchronized with source code updates, with the lowest frequency once a week +* AllInOne pack are updated once a month (packaged, uploaded, and time-consuming) in principle, and you can download the standard deployment package instead + + +# 工程说明 Source Code Project Description +uavstack是UAVStack的All in One源代码仓库。 + +uavstack is the All in One source repository of UAVStack. + +## 根POM +* com.creditease.uav.superpom 根POM,包含依赖管理,Build所需plugins等 (Parent POM for dependency management & build plugins) + +## UAV.Monitor +* com.creditease.uav.agent 监控代理程序MonitorAgent核心框架 (Core of MonitorAgent) +* com.creditease.uav.healthmanager Monitor核心服务,包括实时数据,画像数据存储/查询,实时报警流式计算,AppHub支持服务 (Core feature of HealthManager, including Monitoring Data Service,Application/Service Profiling,Real-time alarm streaming,AppHub Support Service) +* com.creditease.uav.notifycenter Monitor服务:报警中心服务端 (Notification Center Service) +* com.creditease.uav.monitorframework 探针MOF核心框架 (Core of JVM MonitorFramework for Tomcat,Jetty,SpringBoot,MSCP, etc...) +* com.creditease.uav.monitorframework.agent 探针MOF的javaagent实现 (JVM MonitorFramework javaagent support) +* com.creditease.uav.monitorframework.dproxy javaassit支持 (JVM MonitorFramework javassit support) +* com.creditease.uav.hook.* 探针MOF针对技术规范的钩子,包括Dubbo,HttpClients,JAXWS,JDBC,MongoClients,MQ,Redis等 (JVM MonitorFramework Hooks for application framework) +* com.creditease.uav.loghook 探针MOF针对log4j,logback支持 (JVM MonitorFramework Hook for log4j, logback) +* com.creditease.uav.tomcat.plus.core 探针MOF对Tomcat/SpringBoot的支持 (JVM MonitorFramework extension for Tomcat/SpringBoot) +* com.creditease.uav.jetty.plus.core 探针MOF对Jetty支持 (JVM MonitorFramework extension for Jetty) +* com.creditease.uav.mock.sl4j 去除某些框架依赖sl4j (mock sl4j) +* com.creditease.uav.ttl com.alibaba.ttl源代码引入 (Alibaba TTL) +* com.creditease.uav.monitorframework.buildFat WAR测试程序 (Function Test of JVM MonitorFramework) +* com.creditease.uav.monitorframework.springbootFat SpringBoot测试程序 (Function Test of JVM MonitorFramework for springboot) +* com.creditease.uav.agent.buildComponent 制作监控代理程序部署包 (Build POM for MonitorAgent) +* com.creditease.uav.healthmanager.buildComponent 制作健康管理程序部署包 (Build POM for HealthManager) +* com.creditease.uav.monitorframework.buildComponent 制作探针MOF部署包 (Build POM for JVM MonitorFramework) + +## UAV.APM +* com.creditease.uav.collect APM归集客户端/服务端 (Core of APM Data Collection Client & Service) +* com.creditease.uav.invokechain 调用链,日志服务存储和查询 (InvokeChain, Log Collection 2.0) +* com.creditease.uav.monitorframework.apm 探针MOF的APM支持 (JVM MonitorFramework extension for APM) +* com.creditease.uav.threadanalysis 一键式线程分析客户端和服务端 (One Shot Thread Analysis Client & Service) + +## UAV.MSCP +* com.creditease.uav.base MSCP核心框架 (Core of MSCP) +* com.creditease.uav.agent.heartbeat 心跳客户端,心跳服务端,节点远程操控,进程扫描,进程值守 (Base feature of MSCP including heartbeat client & service,node remote opertaions,process auto scanning,process keep-alive support) +* com.creditease.uav.annoscan Fastclasspathscanner源代码引入,注解Class扫描 (Fastclasspathscanner) +* com.creditease.uav.cache.redis 基于Redis的CacheManager (Cache Framework based on redis) +* com.creditease.uav.dbaccess 存储管理器,目前封装了对MySql,OpenTSDB,HBase,MongoDB的存储和查询 (Data Store Framework for MySQL,OpenTSDB,HBase,MongoDB) +* com.creditease.uav.elasticsearch.client ElasticSearch的Shaded客户端封装,避免冲突 (ElasticSearch-Shaded-Client) +* com.creditease.uav.fastjson Fastjson源代码引入 (FastJson) +* com.creditease.uav.helper Util型支持类库 (Util Support Lib) +* com.creditease.uav.httpasync Http异步通信客户端,封装Apache AsyncClient (RPC Framework based on Apache Http AsyncClient) +* com.creditease.uav.logging MSCP日志支持 (MSCP Logging support) +* com.creditease.uav.messaging MSCP消息发送者和消费者支持,无需关心底层消息服务,依赖com.creditease.uav.mq (Messaging Service) +* com.creditease.uav.mq 消息队列服务底层封装,目前使用RocketMQ (Message Queue Support based on Rocket MQ) +* com.creditease.uav.notifymanager MSCP组件级报警支持 (MSCP Component level notification support) +* com.creditease.uav.upgrade MSCP升级客户端和服务端 (Remote upgrading support for MSCP) + +## UAV.AppHub +* com.creditease.uav.console UAVStack交互前端,包括Monitor,APM等前端交互功能 (AppHub is the GUI console for UAVStack) +* com.creditease.uav.console.buildComponent 制作AppHub部署包 (Build POM for AppHub) + +## UAV.ServiceGovern +* 服务自动注册包含与探针MOF代码中 +* 服务发现代码包含与健康管理程序画像数据查询中 +* 服务降级保护(代码整理中,陆续更新...) +* 服务授权(代码整理中,陆续更新...) + +# 如何构建 How to Build +如果由于缺少jar包或某些依赖jar无法下载导致Maven Build Failure,可下载[参考Maven依赖仓库](https://pan.baidu.com/s/1gfeY8pH),使用该Maven仓库或将其复制到你正在使用的Maven仓库中。 + +If you are unable to build because of the lack of jar packages or certain dependency jar, pleaser refer this [Maven Repository](https://pan.baidu.com/s/1gfeY8pH), use the Maven repository, or copy it to the Maven warehouse you are using. + +1. build com.creditease.uav.superpom +``` +cd com.creditease.uav.superpom +mvn clean install +``` +2 中间件增强框架(MOF探针) +``` +cd com.creditease.uav.monitorframework.buildComponent +mvn clean install +``` + +build结果 +>target +> -build +> -uavmof_1.0_XXXXX.zip +> -uavmof_1.0_XXXXX.zip.MD5 + +3. 监控代理程序(MA) +``` +cd com.creditease.uav.agent.buildComponent +mvn clean install +``` + +build结果 +>target +> -build +> -uavagent_1.0_XXXXX.zip +> -uavagent_1.0_XXXXX.zip.MD5 + +4. 健康管理服务(HM) +``` +cd com.creditease.uav.healthmanager.buildComponent +mvn clean install +``` + +build结果 +>target +> -build +> -uavhm_1.0_XXXXX.zip +> -uavhm_1.0_XXXXX.zip.MD5 + +5. AppHub +``` +cd com.creditease.uav.console +mvn clean install +``` + +build结果 +>target +> -com.creditease.uav.console-1.0.war + +# 文档中心 Documents +## 全维监控UAV.Monitor+APM +* [用户指南](https://uavorg.github.io/documents/uavdoc_useroperation/index.html) +* [安装部署](https://uavorg.github.io/documents/uavdoc_deploydocs/index.html) +* [架构说明](https://uavorg.github.io/documents/uavdoc_architecture/index.html) + +# 下载中心 Downloads +## 全维监控UAV.Monitor+APM +* [MOF探针](https://pan.baidu.com/s/1cg4J0q) +* [监控代理程序](https://pan.baidu.com/s/1ge5MJ9h) +* [健康管理服务](https://pan.baidu.com/s/1i4HnV85) +* [AppHub](https://pan.baidu.com/s/1dFxtDZV) + +## 第三方下载 Thirdparty Downloads +* [rocket.war](https://pan.baidu.com/s/1dF6NeHN) + +## AllInOne开发演示版 AllInOne Install Downloads +开发演示版的健康管理服务(HM)仅适合开发环境,演示环境,小规模测试环境。 +生产环境推荐使用[分布式部署](https://uavorg.github.io/documents/uavdoc_deploydocs/healmanagerInstall/healmanagerInstall/microservice.html) + +The health management service (HM) in AllInOne Install Package is only suitable for development environments, demos, and small scale testing environments. [A distributed deployment](https://uavorg.github.io/documents/uavdoc_deploydocs/healmanagerInstall/healmanagerInstall/microservice.html) is recommended for the production environment + +* [Windows64位](https://pan.baidu.com/s/1jIF0wNs) +* [Mac](https://pan.baidu.com/s/1mhCykp6) +* [Linux(CentOS)](https://pan.baidu.com/s/1nvj6jW1) + + + + diff --git a/com.creditease.uav.agent.buildComponent/bin/run.sh b/com.creditease.uav.agent.buildComponent/bin/run.sh index 2c5d3281..4f820367 100644 --- a/com.creditease.uav.agent.buildComponent/bin/run.sh +++ b/com.creditease.uav.agent.buildComponent/bin/run.sh @@ -47,7 +47,7 @@ export CLASSPATH=bin/com.creditease.uav.base-1.0-boot.jar echo $CLASSPATH javaAgent="-javaagent:../uavmof/com.creditease.uav.agent/com.creditease.uav.monitorframework.agent-1.0-agent.jar" javaOpts="-server -Xms64m -Xmx256m -Xss256k -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:CMSIncrementalDutyCycleMin=0 -XX:CMSIncrementalDutyCycle=10 -XX:+UseParNewGC -XX:+UseCMSCompactAtFullCollection -XX:-CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=0 -XX:CMSInitiatingOccupancyFraction=70 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=." -$executeJava $javaAgent $javaOpts -XX:OnOutOfMemoryError='kill -9 %p' -DNetCardIndex=$netcardIndex -DNetCardName=$netcardName -DJAppID=$2 -DJAppGroup=UNKNOWN -classpath $CLASSPATH com.creditease.mscp.boot.MSCPBoot -p $1 & +$executeJava $javaAgent $javaOpts -XX:OnOutOfMemoryError='kill -9 %p' -DNetCardIndex=$netcardIndex -DNetCardName=$netcardName -DJAppID=$2 -DJAppGroup=UAV -classpath $CLASSPATH com.creditease.mscp.boot.MSCPBoot -p $1 & # add crontab process watcher if [ "$proc_watcher" == "yes" ]; then diff --git a/com.creditease.uav.agent.buildComponent/config/agent.properties b/com.creditease.uav.agent.buildComponent/config/agent.properties index d68680a1..35db4f2c 100644 --- a/com.creditease.uav.agent.buildComponent/config/agent.properties +++ b/com.creditease.uav.agent.buildComponent/config/agent.properties @@ -109,6 +109,7 @@ feature.monitoragent.http.enable=false feature.monitoragent.jvm.filters=com.sun.tools,sun.tools,jenkins-cli.jar,com.creditease.agent.feature.nodeopagent.NodeOperCtrlClient #monitoragent detect interval default is 30000 feature.monitoragent.detector.interval=30000 +feature.monitoragent.detector.profilehbtimeout=15000 #enable local scan by jvm tool and jmx feature.monitoragent.detector.local.scan.enable=true #enable container scan by http @@ -144,6 +145,8 @@ feature.logagent.MutiThread.enable=true feature.logagent.MutiThread.thread.max=2 #default filter feature.logagent.defrule.filter= +#LOGAGENT LOG LEVEL +feature.logagent.log.level=DEBUG #Proc Detect Agent Feature feature.procscan.loader=com.creditease.uav.agent.heartbeat.jar diff --git a/com.creditease.uav.agent.buildComponent/config/ma_pro.properties b/com.creditease.uav.agent.buildComponent/config/ma_pro.properties index edea2c33..453d3c88 100644 --- a/com.creditease.uav.agent.buildComponent/config/ma_pro.properties +++ b/com.creditease.uav.agent.buildComponent/config/ma_pro.properties @@ -16,7 +16,7 @@ meta.nodetype=\u76D1\u63A7\u4EE3\u7406\u7A0B\u5E8F #resource components #resource.xxxx -resource.messageproducer.class=com.creditease.agent.feature.common.MessageProducerResourceComponent +resource.messageproducer.class=org.uavstack.resources.common.messaging.MessageProducerResourceComponent #resource.xxxx.properties, for example: =,=,... resource.messageproducer.properties= #resource.xxxx. @@ -27,7 +27,7 @@ resource.messageproducer.messagingthreshold=30 resource.messageproducer.messagesizelimit=262000 #System Http Invoker -resource.httpinvoke.class=com.creditease.agent.feature.common.HttpInvokerResourceComponent +resource.httpinvoke.class=org.uavstack.resources.common.invoker.HttpInvokerResourceComponent resource.httpinvoke.properties= resource.httpinvoke.http.client.maxperroute=20 resource.httpinvoke.http.client.maxtotal=100 @@ -36,14 +36,14 @@ resource.httpinvoke.http.client.conntimeout=10000 resource.httpinvoke.http.client.reqtimeout=10000 #nodeoperagent -feature.nodeoperagent.loader=default +feature.nodeoperagent.loader=com.creditease.uav.agent.heartbeat.jar #feature.xxx.enable should enable this feature feature.nodeoperagent.enable=true feature.nodeoperagent.components=com.creditease.agent.feature.NodeOperAgent feature.nodeoperagent.http.port=10101 #notifyagent -feature.notifyagent.loader=default +feature.notifyagent.loader=com.creditease.uav.notifymanager.jar #feature.xxx.enable should enable this feature feature.notifyagent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -58,7 +58,7 @@ feature.notifyagent.frozenTime=300 #heartbeatclientagent Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.hbclientagent.loader=default +feature.hbclientagent.loader=com.creditease.uav.agent.heartbeat.jar #feature.xxx.enable should enable this feature feature.hbclientagent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -73,7 +73,7 @@ feature.hbclientagent.interval=15000 #agent feature configuration #Monitor Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.monitoragent.loader=default +feature.monitoragent.loader=com.creditease.uav.agent-1.0.jar #feature.xxx.enable should enable this feature feature.monitoragent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -101,10 +101,11 @@ feature.monitoragent.http.enable=false feature.monitoragent.jvm.filters=com.sun.tools,sun.tools,jenkins-cli.jar,com.creditease.agent.feature.nodeopagent.NodeOperCtrlClient #monitoragent detect interval default is 30000 feature.monitoragent.detector.interval=30000 +feature.monitoragent.detector.profilehbtimeout=15000 #enable local scan by jvm tool and jmx feature.monitoragent.detector.local.scan.enable=true #enable container scan by http -feature.monitoragent.detector.container.scan.enable=false +feature.monitoragent.detector.container.scan.enable=true #container ports feature.monitoragent.detector.container.ports= #monitoragent detect interval default is 15000 @@ -118,7 +119,7 @@ feature.monitoragent.limit.cpu.timerange=120000 #Log Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.logagent.loader=default +feature.logagent.loader=com.creditease.uav.agent-1.0.jar #feature.xxx.enable should enable this feature feature.logagent.enable=true #feature.xxx.enable should enable the self Log collection feature @@ -136,9 +137,11 @@ feature.logagent.MutiThread.enable=true feature.logagent.MutiThread.thread.max=2 #default filter feature.logagent.defrule.filter= +#LOGAGENT LOG LEVEL +feature.logagent.log.level=DEBUG #Proc Detect Agent Feature -feature.procscan.loader=default +feature.procscan.loader=com.creditease.uav.agent.heartbeat.jar feature.procscan.enable=true feature.procscan.components=com.creditease.agent.feature.ProcDetectAgent feature.procscan.properties= @@ -148,13 +151,13 @@ feature.procscan.networkDetect.interval=15000 feature.procscan.networkDetect.collectTime=2000 # Process Watch Feature -feature.procwatch.loader=default +feature.procwatch.loader=com.creditease.uav.agent.heartbeat.jar feature.procwatch.enable=true feature.procwatch.interval=15000 feature.procwatch.components=com.creditease.agent.feature.ProcWatchAgent # Data Collect Feature -feature.collectclient.loader=default +feature.collectclient.loader=com.creditease.uav.collect.jar feature.collectclient.enable=true feature.collectclient.components=com.creditease.uav.collect.client.CollectDataAgent feature.collectclient.properties= @@ -167,6 +170,6 @@ feature.collectclient.writeposinterval=3000 feature.collectclient.idlecheckerdelay=12000 feature.collectclient.idlecheckerinterval=5000 # Thread Analysis Feature -feature.threadanalysis.loader=default +feature.threadanalysis.loader=com.creditease.uav.threadanalysis.jar feature.threadanalysis.enable=true feature.threadanalysis.components=com.creditease.uav.threadanalysis.client.ThreadAnalysisAgent diff --git a/com.creditease.uav.agent.buildComponent/config/ma_test.properties b/com.creditease.uav.agent.buildComponent/config/ma_test.properties index 26fbb398..b8498ac7 100644 --- a/com.creditease.uav.agent.buildComponent/config/ma_test.properties +++ b/com.creditease.uav.agent.buildComponent/config/ma_test.properties @@ -16,7 +16,7 @@ meta.nodetype=\u76D1\u63A7\u4EE3\u7406\u7A0B\u5E8F #resource components #resource.xxxx -resource.messageproducer.class=com.creditease.agent.feature.common.MessageProducerResourceComponent +resource.messageproducer.class=org.uavstack.resources.common.messaging.MessageProducerResourceComponent #resource.xxxx.properties, for example: =,=,... resource.messageproducer.properties= #resource.xxxx. @@ -27,7 +27,7 @@ resource.messageproducer.messagingthreshold=30 resource.messageproducer.messagesizelimit=262000 #System Http Invoker -resource.httpinvoke.class=com.creditease.agent.feature.common.HttpInvokerResourceComponent +resource.httpinvoke.class=org.uavstack.resources.common.invoker.HttpInvokerResourceComponent resource.httpinvoke.properties= resource.httpinvoke.http.client.maxperroute=20 resource.httpinvoke.http.client.maxtotal=100 @@ -36,14 +36,14 @@ resource.httpinvoke.http.client.conntimeout=10000 resource.httpinvoke.http.client.reqtimeout=10000 #nodeoperagent -feature.nodeoperagent.loader=default +feature.nodeoperagent.loader=com.creditease.uav.agent.heartbeat.jar #feature.xxx.enable should enable this feature feature.nodeoperagent.enable=true feature.nodeoperagent.components=com.creditease.agent.feature.NodeOperAgent feature.nodeoperagent.http.port=10101 #notifyagent -feature.notifyagent.loader=default +feature.notifyagent.loader=com.creditease.uav.notifymanager.jar #feature.xxx.enable should enable this feature feature.notifyagent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -58,7 +58,7 @@ feature.notifyagent.frozenTime=300 #heartbeatclientagent Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.hbclientagent.loader=default +feature.hbclientagent.loader=com.creditease.uav.agent.heartbeat.jar #feature.xxx.enable should enable this feature feature.hbclientagent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -73,7 +73,7 @@ feature.hbclientagent.interval=15000 #agent feature configuration #Monitor Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.monitoragent.loader=default +feature.monitoragent.loader=com.creditease.uav.agent-1.0.jar #feature.xxx.enable should enable this feature feature.monitoragent.enable=true #feature.xxx.components is the component classes (extends com.creditease.agent.spi.AgentFeatureComponent), separator "," for multiply classes @@ -101,10 +101,11 @@ feature.monitoragent.http.enable=false feature.monitoragent.jvm.filters=com.sun.tools,sun.tools,jenkins-cli.jar,com.creditease.agent.feature.nodeopagent.NodeOperCtrlClient #monitoragent detect interval default is 30000 feature.monitoragent.detector.interval=30000 +feature.monitoragent.detector.profilehbtimeout=15000 #enable local scan by jvm tool and jmx feature.monitoragent.detector.local.scan.enable=true #enable container scan by http -feature.monitoragent.detector.container.scan.enable=false +feature.monitoragent.detector.container.scan.enable=true #container ports feature.monitoragent.detector.container.ports= #monitoragent detect interval default is 15000 @@ -118,7 +119,7 @@ feature.monitoragent.limit.cpu.timerange=120000 #Log Agent Feature xxx #feature.xxx.loader should be a jar file path or default -feature.logagent.loader=default +feature.logagent.loader=com.creditease.uav.agent-1.0.jar #feature.xxx.enable should enable this feature feature.logagent.enable=true #feature.xxx.enable should enable the self Log collection feature @@ -136,9 +137,11 @@ feature.logagent.MutiThread.enable=true feature.logagent.MutiThread.thread.max=2 #default filter feature.logagent.defrule.filter= +#LOGAGENT LOG LEVEL +feature.logagent.log.level=DEBUG #Proc Detect Agent Feature -feature.procscan.loader=default +feature.procscan.loader=com.creditease.uav.agent.heartbeat.jar feature.procscan.enable=true feature.procscan.components=com.creditease.agent.feature.ProcDetectAgent feature.procscan.properties= @@ -148,13 +151,13 @@ feature.procscan.networkDetect.interval=15000 feature.procscan.networkDetect.collectTime=2000 # Process Watch Feature -feature.procwatch.loader=default +feature.procwatch.loader=com.creditease.uav.agent.heartbeat.jar feature.procwatch.enable=true feature.procwatch.interval=15000 feature.procwatch.components=com.creditease.agent.feature.ProcWatchAgent # Data Collect Feature -feature.collectclient.loader=default +feature.collectclient.loader=com.creditease.uav.collect.jar feature.collectclient.enable=true feature.collectclient.components=com.creditease.uav.collect.client.CollectDataAgent feature.collectclient.properties= @@ -167,6 +170,6 @@ feature.collectclient.writeposinterval=3000 feature.collectclient.idlecheckerdelay=12000 feature.collectclient.idlecheckerinterval=5000 # Thread Analysis Feature -feature.threadanalysis.loader=default +feature.threadanalysis.loader=com.creditease.uav.threadanalysis.jar feature.threadanalysis.enable=true feature.threadanalysis.components=com.creditease.uav.threadanalysis.client.ThreadAnalysisAgent \ No newline at end of file diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/hbagent/HeartBeatServerLifeKeeper.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/hbagent/HeartBeatServerLifeKeeper.java index 2fa79b8a..204035de 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/hbagent/HeartBeatServerLifeKeeper.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/hbagent/HeartBeatServerLifeKeeper.java @@ -41,7 +41,7 @@ public class HeartBeatServerLifeKeeper extends AbstractTimerWork { private long lockTimeout = 60000; - private long nodeDyingTimeout = 40000; + private long nodeDyingTimeout = 15000; private CacheManager cacheManager; @@ -129,19 +129,19 @@ public void run() { } // node is in dying state - if (timeout >= this.nodeDyingTimeout && timeout < this.nodeDyingTimeout * 5) { + if (timeout >= this.nodeDyingTimeout && timeout < this.nodeDyingTimeout * 2) { nodeInfo.putInfo(InfoType.Node, "state", "0"); nodeInfoMap.put(nodeId, nodeInfo.toJSONString()); cm.putHash(HeartBeatProtocol.STORE_REGION_UAV, HeartBeatProtocol.STORE_KEY_NODEINFO, nodeInfoMap); } // node is in dead state - else if (timeout >= this.nodeDyingTimeout * 5 && timeout < this.nodeDyingTimeout * 10) { + else if (timeout >= this.nodeDyingTimeout * 2 && timeout < this.nodeDyingTimeout * 3) { nodeInfo.putInfo(InfoType.Node, "state", "-1"); nodeInfoMap.put(nodeId, nodeInfo.toJSONString()); cm.putHash(HeartBeatProtocol.STORE_REGION_UAV, HeartBeatProtocol.STORE_KEY_NODEINFO, nodeInfoMap); } // clean this node info - else if (timeout >= this.nodeDyingTimeout * 10) { + else if (timeout >= this.nodeDyingTimeout * 3) { cm.delHash(HeartBeatProtocol.STORE_REGION_UAV, HeartBeatProtocol.STORE_KEY_NODEINFO, nodeId); } } diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/NodeOperCtrlHandler.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/NodeOperCtrlHandler.java index 0f82a4f8..03c69617 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/NodeOperCtrlHandler.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/NodeOperCtrlHandler.java @@ -66,9 +66,9 @@ public void handle(UAVHttpMessage data) { Long ts = actionLimits.get(intent); - if (ts != null && curTS - ts < 60000 + if (ts != null && curTS - ts < 1000 && (!"loadnodepro".equalsIgnoreCase(intent) && !"chgsyspro".equalsIgnoreCase(intent))) { - data.putResponse("rs", "该节点上的操作[" + intent + "]1分钟内只能进行一次"); + data.putResponse("rs", "该节点上的操作[" + intent + "]1秒内只能进行一次"); return; } diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFCtrlAction.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFCtrlAction.java index 8ccc6231..32a7995e 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFCtrlAction.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFCtrlAction.java @@ -86,13 +86,26 @@ public void completed(HttpClientCallbackResult result) { String res = result.getReplyDataAsString(); - log.info(this, "MOFCtrlAction Success: url=" + url + ", res=" + res); - - if (!StringHelper.isEmpty(res)) { - isSuccess.set(true); + if (result.getRetCode() >= 400) { + log.err(this, + "MOFCtrlAction FAIL: retcode=" + result.getRetCode() + ", url=" + url + ", err=" + res); + if (result.getRetCode() >= 500) { + response.append("请求" + url + "完成时的状态码为【" + result.getRetCode() + "】, 服务器遇到错误而不能完成该请求."); + } + else { + response.append("请求" + url + "完成时的状态码为【" + result.getRetCode() + "】, 请求客户端错误."); + } + + isSuccess.set(false); + } + else { + response.append(res); + log.info(this, + "MOFCtrlAction Success: retcode=" + result.getRetCode() + ", url=" + url + ", res=" + res); + if (!StringHelper.isEmpty(res)) { + isSuccess.set(true); + } } - - response.append(res); cdl.countDown(); } diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFInstallMgtAction.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFInstallMgtAction.java index ea46d723..f3760cc8 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFInstallMgtAction.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/nodeopagent/actions/MOFInstallMgtAction.java @@ -20,6 +20,7 @@ package com.creditease.agent.feature.nodeopagent.actions; +import java.io.File; import java.util.LinkedList; import java.util.List; @@ -192,6 +193,14 @@ private void installMOFforTomcat(String shellParentPath, String agentArgs) throw for (String filePath : filePaths) { + if (!IOHelper.exists(filePath)) { + try { + new File(filePath).createNewFile(); + } + catch (Exception e) { + log.err(this, "UNInstall UAVMOF FAIL:filePath=" + filePath + " not exits and create file fail", e); + } + } String content = IOHelper.readTxtFile(filePath, "UTF-8"); String[] lines = content.split("\n"); diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procdetectagent/NetworkIoDetector.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procdetectagent/NetworkIoDetector.java index f11c9fd9..dd90c00b 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procdetectagent/NetworkIoDetector.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procdetectagent/NetworkIoDetector.java @@ -60,19 +60,20 @@ public void run() { // windows if (JVMToolHelper.isWindows()) { - + + JpcapCaptor jpcap =null; try { String Local_ip = "/" + ip; - // ˿ + // 存端口流量 HashMap counter = new HashMap(); String[] split_ProtList = portList.split(" "); for (String str : split_ProtList) { counter.put("in_" + str, 0); counter.put("out_" + str, 0); } - // ȡ豸б + // 获取网卡设备列表 NetworkInterface[] devices = JpcapCaptor.getDeviceList(); - // ȷ豸ӿ + // 确定网卡设备接口 boolean true_devices = false; int i = 0; for (; i < devices.length; i++) { @@ -88,17 +89,23 @@ public void run() { } } NetworkInterface nc = devices[i]; - // 豸 ijϵץȡ,Ϊ65535 - JpcapCaptor jpcap = JpcapCaptor.openDevice(nc, 65535, false, 20); - jpcap.setFilter("tcp", true);// ù + // 打开网卡设备 ,创建某个卡口上的抓取对象,最大为65535个 + jpcap = JpcapCaptor.openDevice(nc, 65535, false, 20); + jpcap.setFilter("tcp", true);// 设置过滤器 - // ץ ͳ + // 抓包 统计流量 result = portFlux(jpcap, counter, nc, networkdetectTime, Local_ip); } catch (Exception e) { log.err(this, "NetworkIo Monitor runs FAIL.", e); } + finally { + if(jpcap!=null) { + // 关闭 + jpcap.close(); + } + } } @@ -157,16 +164,16 @@ public String portFlux(JpcapCaptor jpcap, HashMap counter, Netw long time = Long.parseLong(networkdetectTime); long startTime = System.currentTimeMillis(); while (startTime + time >= System.currentTimeMillis()) { - // ץ + // 抓包 packet = jpcap.getPacket(); if (null == packet) { continue; } TCPPacket p = (TCPPacket) packet; - // ˿ڲprotList + // 端口不在protList 忽略 String dst_ip = p.dst_ip.toString(); String src_ip = p.src_ip.toString(); - // ͳ + // 统计入口流量 if (dst_ip.equals(Local_ip)) { String in_port = "in_" + p.dst_port; if (counter.containsKey(in_port)) { @@ -174,7 +181,7 @@ public String portFlux(JpcapCaptor jpcap, HashMap counter, Netw counter.put(in_port, in_value); } } - // ͳƳ + // 统计出口流量 if (src_ip.equals(Local_ip)) { String out_port = "out_" + p.src_port; if (counter.containsKey(out_port)) { @@ -185,13 +192,13 @@ public String portFlux(JpcapCaptor jpcap, HashMap counter, Netw } HashMap counterValueIntToString = new HashMap(); - // ֽתkb/s + // 字节转kb/s for (String key : counter.keySet()) { DecimalFormat df = new DecimalFormat("#0.00"); Double value = Double.valueOf(df.format(counter.get(key) / int_networkdetectTime * 1.0)); counterValueIntToString.put(key, value.toString()); } - // hashmap תΪjson + // 将hashmap 转为json 返回 return JSONHelper.toString(counterValueIntToString); } diff --git a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procwatch/ProcWatcher.java b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procwatch/ProcWatcher.java index 5b275da4..89fa6559 100644 --- a/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procwatch/ProcWatcher.java +++ b/com.creditease.uav.agent.heartbeat/src/main/java/com/creditease/agent/feature/procwatch/ProcWatcher.java @@ -260,7 +260,7 @@ private void notify(ProcInfo proc, String startedMsg) { String desc = "发现" + proc.getName() + "进程" + proc.getPid() + "停止,已重启。\n启动参数:" + proc.getCmd() + "\n启动信息:" + startedMsg; - NotificationEvent event = new NotificationEvent(NotificationEvent.EVENT_Tag_NoBlock, + NotificationEvent event = new NotificationEvent(NotificationEvent.EVENT_RT_ALERT_CRASH, "发现" + proc.getName() + "进程停止,已重启进程", desc); putNotificationEvent(event); } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/LogAgent.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/LogAgent.java index 6025049a..5405f0a7 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/LogAgent.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/LogAgent.java @@ -223,7 +223,11 @@ public LogAgent(String cName, String feature) { @Override protected ISystemLogger getLogger(String cName, String feature) { - return SystemLogger.getLogger("LogDataLog", feature + ".logd.%g.%u.log", "DEBUG", true, 5 * 1024 * 1024); + return SystemLogger.getLogger("LogDataLog", feature + ".logd.%g.%u.log", + StringHelper.isEmpty(this.getConfigManager().getFeatureConfiguration(this.feature, "log.level")) + ? "DEBUG" + : this.getConfigManager().getFeatureConfiguration(this.feature, "log.level"), + true, 5 * 1024 * 1024); } @Override @@ -669,7 +673,7 @@ public int compare(LogPatternInfo o1, LogPatternInfo o2) { * in some cases there are may no log pattern infos */ if (logCatcherInfoMap.isEmpty()) { - log.warn(this, + log.debug(this, "The logCatcherInfoMap is empty and will not update log pattern info in ProfileData for logCatcher."); return; } @@ -714,7 +718,7 @@ public int compare(LogPatternInfo o1, LogPatternInfo o2) { else { logCatcher.configure(logCatcherInfoMap); - log.info(this, "ApplicationServer LogCatcher updates SUCCESS"); + log.debug(this, "ApplicationServer LogCatcher updates SUCCESS"); } } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/MonitorAgent.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/MonitorAgent.java index 471d7c1c..5cd13bad 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/MonitorAgent.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/MonitorAgent.java @@ -111,8 +111,27 @@ private void startAppServerMonitorDetector() { // init DetectorManager DetectorManager appServerMonitorDetector_TimerWorker = new DetectorManager( - "AppServerMonitorDetector_TimerWorker", this.feature); + "AppServerMonitorDetector_TimerWorker", this.feature); + boolean isContainerDetectEnable = DataConvertHelper.toBoolean( + this.getConfigManager().getFeatureConfiguration(this.feature, "detector.container.scan.enable"), false); + + if (isContainerDetectEnable == true) { + // init JVMContainerOSDetector + JVMContainerOSDetector cosd = new JVMContainerOSDetector("JVMContainerOSDetector", this.feature, + "modatahandlers", detectInterval); + + cosd.register("appserver", + "com.creditease.agent.feature.monitoragent.datacatch.http.HttpAppServerMonitorDataCatchWorker"); + cosd.register("mscp", + "com.creditease.agent.feature.monitoragent.datacatch.http.HttpMSCPMonitorDataCatchWorker"); + cosd.register("springboot", + "com.creditease.agent.feature.monitoragent.datacatch.http.HttpSpringBootMonitorDataCatchWorker"); + + // install JVMContainerOSDetector + appServerMonitorDetector_TimerWorker.installDetector(cosd); + } + boolean isLocalOSDetectEnable = DataConvertHelper.toBoolean( this.getConfigManager().getFeatureConfiguration(this.feature, "detector.local.scan.enable"), true); @@ -133,26 +152,7 @@ private void startAppServerMonitorDetector() { // install JVMLocalOSDetector appServerMonitorDetector_TimerWorker.installDetector(asmd); } - - boolean isContainerDetectEnable = DataConvertHelper.toBoolean( - this.getConfigManager().getFeatureConfiguration(this.feature, "detector.container.scan.enable"), false); - - if (isContainerDetectEnable == true) { - // init JVMContainerOSDetector - JVMContainerOSDetector cosd = new JVMContainerOSDetector("JVMContainerOSDetector", this.feature, - "modatahandlers", detectInterval); - - cosd.register("appserver", - "com.creditease.agent.feature.monitoragent.datacatch.http.HttpAppServerMonitorDataCatchWorker"); - cosd.register("mscp", - "com.creditease.agent.feature.monitoragent.datacatch.http.HttpMSCPMonitorDataCatchWorker"); - cosd.register("springboot", - "com.creditease.agent.feature.monitoragent.datacatch.http.HttpSpringBootMonitorDataCatchWorker"); - - // install JVMContainerOSDetector - appServerMonitorDetector_TimerWorker.installDetector(cosd); - } - + // start ApplicationServerMonitorDetector this.getTimerWorkManager().scheduleWork("AppServerMonitorDetector_TimerWorker", appServerMonitorDetector_TimerWorker, 0, detectInterval); diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/ReliableTaildirEventReader.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/ReliableTaildirEventReader.java index d14d8ffb..44987c64 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/ReliableTaildirEventReader.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/ReliableTaildirEventReader.java @@ -188,29 +188,35 @@ public void loadPositionFile(String filePath) { inode = positionObject.getLong("inode"); pos = positionObject.getLong("pos"); file = positionObject.getString("file"); - // add line number - number = positionObject.getLongValue("num"); - for (Object v : Arrays.asList(inode, pos, file)) { - Preconditions.checkNotNull(v, "Detected missing value in position file. " + "inode: " + inode - + ", pos: " + pos + ", path: " + file); - } - TailFile tf = tailFiles.get(inode); - if (tf != null && tf.updatePos(file, inode, pos, number)) { - tailFiles.put(inode, tf); + Long currentInode = getInode(new File(file)); + if (!currentInode.equals(inode)) { + maybeReloadMap.remove(inode); } else { - // add old tail file into memory - maybeReloadMap.put(inode, new Long[] { pos, number }); - if (logger.isDebugEnable()) { - logger.debug(this, "add old&inInterrupt file: " + file + ", inode: " + inode + ", pos: " + pos); + // add line number + number = positionObject.getLongValue("num"); + for (Object v : Arrays.asList(inode, pos, file)) { + Preconditions.checkNotNull(v, "Detected missing value in position file. " + "inode: " + inode + + ", pos: " + pos + ", path: " + file); + } + TailFile tf = tailFiles.get(inode); + if (tf != null && tf.updatePos(file, inode, pos, number)) { + tailFiles.put(inode, tf); } + else { + // add old tail file into memory + maybeReloadMap.put(inode, new Long[] { pos, number }); + if (logger.isDebugEnable()) { + logger.debug(this, "add old&inInterrupt file: " + file + ", inode: " + inode + ", pos: " + pos); + } + } } } } catch (FileNotFoundException e1) { - logger.info(this, "File not found: " + filePath + ", not updating position"); + logger.err(this, "File not found: " + filePath + ", not updating position"); } catch (IOException e) { logger.err(this, "Failed loading positionFile: " + filePath, e); @@ -393,6 +399,7 @@ else if (logPatternInfo2.getFlag() == StateFlag.EXIST) { } for (File f : files) { long inode = getInode(f); + removeInvalidTFInode(f, inode); TailFile tf = tailFiles.get(inode); if (tf == null || !tf.getPath().equals(f.getAbsolutePath())) { long startPos = skipToEnd ? f.length() : 0;// 第一次读取从头开始读 @@ -432,6 +439,19 @@ else if (logPatternInfo2.getFlag() == StateFlag.EXIST) { return updatedInodes; } + /** + * @param f + * @param inodeCurrent + */ + private void removeInvalidTFInode(File f, long inodeCurrent) { + for (Long inodeKey : tailFiles.keySet()) { + TailFile tf = tailFiles.get(inodeKey); + if (tf.getPath().equals(f.getAbsolutePath()) && inodeKey != inodeCurrent) { + tailFiles.remove(inodeKey); + } + } + } + public List updateTailFiles() throws IOException { return updateTailFiles(false); diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TailFileTaskJob.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TailFileTaskJob.java index b52d78e1..5790e1ed 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TailFileTaskJob.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TailFileTaskJob.java @@ -81,8 +81,9 @@ protected void work() { log.err(this, "Unable to tail files.", t); } finally { - log.err(this, "finally invoked..."); - + if (log.isDebugEnable()) { + log.debug(this, "finally invoked..."); + } if (null != serverlogs) { serverlogs.clear(); } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TaildirLogComponent.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TaildirLogComponent.java index 3b047ce9..c81ba5e6 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TaildirLogComponent.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/logagent/TaildirLogComponent.java @@ -182,10 +182,10 @@ public synchronized void stop() { reader.close(); } catch (InterruptedException e) { - log.info(this, "Interrupted while awaiting termination", e); + log.err(this, "Interrupted while awaiting termination", e); } catch (IOException e) { - log.info(this, "Failed: " + e.getMessage(), e); + log.err(this, "Failed: " + e.getMessage(), e); } // sourceCounter.stop(); log.info("Taildir source {} stopped.", cName); diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseHttpMonitorDataCatchWorker.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseHttpMonitorDataCatchWorker.java index e9f7f189..b759f8bc 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseHttpMonitorDataCatchWorker.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseHttpMonitorDataCatchWorker.java @@ -75,13 +75,18 @@ public void setE(Throwable e) { } } - protected HttpAsyncClient client; + private HttpAsyncClient client; + + private long profileHBTimeout; public BaseHttpMonitorDataCatchWorker(String cName, String feature, JVMAgentInfo appServerInfo, BaseDetector detector) { + super(cName, feature, appServerInfo, detector); - client = HttpAsyncClientFactory.build(2, 5, 2, 2, 2); + String profileHBTimeoutStr = this.getConfigManager().getFeatureConfiguration(feature, + "detector.profilehbtimeout"); + profileHBTimeout = StringHelper.isEmpty(profileHBTimeoutStr) ? 15000 : Long.parseLong(profileHBTimeoutStr); } @Override @@ -203,7 +208,7 @@ protected boolean doCaptureProfileData(long timeFlag, MonitorDataFrame pmdf) thr * this data is old, but need for profile heartbeat even the if Update = false, but we will still pass the * profile data as a heartbeat for profiledata the heart beat interval = 1 min */ - else if (isUpdate == false && curTime - state.getProfileTimestamp() > 60000) { + else if (isUpdate == false && curTime - state.getProfileTimestamp() > profileHBTimeout) { isRefreshTimestamp = true; pmdf.setTag("P:HB"); } @@ -237,16 +242,7 @@ else if (isUpdate == false && curTime - state.getProfileTimestamp() > 60000) { * * NOTE: if there is no special appgroup, use MonitorAgent appgroup */ - String uavMAAppGroup = System.getProperty("JAppGroup"); - - String appGroup = this.appServerInfo.getSystemProperties().getProperty("JAppGroup"); - - if (!StringHelper.isEmpty(appGroup)) { - webapp.put("appgroup", appGroup); - } - else if (!StringHelper.isEmpty(uavMAAppGroup)) { - webapp.put("appgroup", uavMAAppGroup); - } + webapp.put("appgroup", this.getAppGroup()); /** * 【2】自定义指标 @@ -384,10 +380,10 @@ public void failed(HttpClientCallbackResult result) { }; if (postData == null) { - client.doAsyncHttpGet(serviceURL, callback); + getHttpAsyncClient().doAsyncHttpGet(serviceURL, callback); } else { - client.doAsyncHttpPost(serviceURL, postData, callback); + getHttpAsyncClient().doAsyncHttpPost(serviceURL, postData, callback); } // timeout for response @@ -437,4 +433,29 @@ public int start() { return 1; } + @Override + public void cancel() { + + super.cancel(); + + if (client != null) { + client.shutdown(); + } + } + + /** + * get HttpAsyncClient unsafe + * + * @return HttpAsyncClient + */ + private HttpAsyncClient getHttpAsyncClient() { + + if (client != null) { + return client; + } + + client = HttpAsyncClientFactory.build(2, 5, 2000, 2000, 2000); + + return client; + } } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseMonitorDataCatchWorker.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseMonitorDataCatchWorker.java index e84f2a9d..f45cf1b7 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseMonitorDataCatchWorker.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/BaseMonitorDataCatchWorker.java @@ -77,6 +77,7 @@ public void setProfileTimestamp(long t) { protected Map customizedMetrics = new HashMap<>(); public BaseMonitorDataCatchWorker(String cName, String feature, JVMAgentInfo appServerInfo, BaseDetector detector) { + super(cName, feature); this.detector = detector; this.appServerInfo = appServerInfo; @@ -155,7 +156,8 @@ protected String getAppGroup() { /** * NOTE: if there is no special appgroup, use MonitorAgent appgroup */ - if (!StringHelper.isEmpty(uavMAAppGroup) && StringHelper.isEmpty(appGroup)) { + if (!StringHelper.isEmpty(uavMAAppGroup) && (StringHelper.isEmpty(appGroup) + || "UNKNOWN".equalsIgnoreCase(appGroup))) { appGroup = uavMAAppGroup; } return appGroup; @@ -204,4 +206,9 @@ public String getWorkerIdFromSystemProForAppServer() { return workerid; } + + public String getDetectorName() { + + return detector.getName(); + } } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXAppServerMonitorDataCatchWorker.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXAppServerMonitorDataCatchWorker.java index 92a55d36..b3b44136 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXAppServerMonitorDataCatchWorker.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXAppServerMonitorDataCatchWorker.java @@ -45,9 +45,16 @@ public class JMXAppServerMonitorDataCatchWorker extends BaseJMXMonitorDataCatchWorker { + private long profileHBTimeout; + public JMXAppServerMonitorDataCatchWorker(String cName, String feature, JVMAgentInfo appServerInfo, BaseDetector detector) { + super(cName, feature, appServerInfo, detector); + + String profileHBTimeoutStr = this.getConfigManager().getFeatureConfiguration(feature, + "detector.profilehbtimeout"); + profileHBTimeout = StringHelper.isEmpty(profileHBTimeoutStr) ? 15000 : Long.parseLong(profileHBTimeoutStr); } @Override @@ -184,7 +191,7 @@ protected boolean doCaptureProfileData(MBeanServerConnection mbsc, long timeFlag * this data is old, but need for profile heartbeat even the if Update = false, but we will still pass * the profile data as a heartbeat for profiledata the heart beat interval = 1 min */ - else if (isUpdate == false && curTime - state.getProfileTimestamp() > 60000) { + else if (isUpdate == false && curTime - state.getProfileTimestamp() > profileHBTimeout) { isRefreshTimestamp = true; pmdf.setTag("P:HB"); } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXJavaMonitorDataCatchWorker.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXJavaMonitorDataCatchWorker.java index 4af36b73..84e5d723 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXJavaMonitorDataCatchWorker.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/datacatch/jmx/JMXJavaMonitorDataCatchWorker.java @@ -159,11 +159,18 @@ public Map handle(ObjectInstance oi, MBeanServerConnection mbsc) // localIP protected String localIP; + private long profileHBTimeout; + public JMXJavaMonitorDataCatchWorker(String cName, String feature, JVMAgentInfo appServerInfo, BaseDetector detector) { + super(cName, feature, appServerInfo, detector); collectJavaProcRunInfo(appServerInfo); + + String profileHBTimeoutStr = this.getConfigManager().getFeatureConfiguration(feature, + "detector.profilehbtimeout"); + profileHBTimeout = StringHelper.isEmpty(profileHBTimeoutStr) ? 15000 : Long.parseLong(profileHBTimeoutStr); } /** @@ -271,7 +278,7 @@ private void doCaptureProfileData(long timeFlag) { else { long curTime = System.currentTimeMillis(); - if (curTime - state.getProfileTimestamp() < 60000) { + if (curTime - state.getProfileTimestamp() < profileHBTimeout) { return; } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/BaseDetector.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/BaseDetector.java index 4fdb3672..fb0b8d5f 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/BaseDetector.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/BaseDetector.java @@ -47,7 +47,7 @@ public abstract class BaseDetector protected final Map workerTypeClsMap = new ConcurrentHashMap(); - protected final Map workers = new ConcurrentHashMap(); + protected Map workers; protected final Map jvmAgentInfos = new ConcurrentHashMap(); @@ -93,7 +93,9 @@ protected void addWorker(JVMAgentInfo appServerInfo) { /** * If the worker exists, just update the appServerInfo this is the hyperspace dark tech, hehe, hehe, hehe :) */ - this.workers.get(workerName).setAppServerInfo(appServerInfo); + if(this.cName.equals(this.workers.get(workerName).getDetectorName())) { + this.workers.get(workerName).setAppServerInfo(appServerInfo); + } return; } @@ -117,6 +119,7 @@ protected void addWorker(JVMAgentInfo appServerInfo) { int res = worker.start(); if (res == -1) { + worker.cancel(); return; } @@ -127,6 +130,7 @@ protected void addWorker(JVMAgentInfo appServerInfo) { worker = newWoker(appServerInfo, workerName, "unknown"); if (worker.start() == -1) { + worker.cancel(); return; } } @@ -137,7 +141,7 @@ protected void addWorker(JVMAgentInfo appServerInfo) { this.workers.put(workerName, worker); // save appserverinfo - this.jvmAgentInfos.put(worker.getWorkerId(), appServerInfo); + this.jvmAgentInfos.put(workerName, appServerInfo); log.info(this, worker.getClass().getSimpleName() + "[" + workerName + "] started"); } @@ -178,7 +182,7 @@ public void stop() { // cancel worker worker.cancel(); - this.jvmAgentInfos.remove(worker.getWorkerId()); + this.jvmAgentInfos.remove(worker.getName()); log.info(this, "MonitorDataCatchWorker[" + worker.getName() + "] stopped"); } @@ -197,7 +201,7 @@ public void removeWorker(String workName) { worker.cancel(); - this.jvmAgentInfos.remove(worker.getWorkerId()); + this.jvmAgentInfos.remove(workName); log.info(this, "MonitorDataCatchWorker[" + worker.getName() + "] stopped"); } @@ -263,4 +267,12 @@ protected String matchJVMType(JVMAgentInfo appServerInfo) throws RuntimeExceptio return jvmType; } + + /** + * @param set the workers + */ + protected void setWorkers(Map workers) { + + this.workers = workers; + } } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/DetectorManager.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/DetectorManager.java index 2de7d9b3..0dba27f0 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/DetectorManager.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/DetectorManager.java @@ -22,7 +22,9 @@ import java.util.LinkedHashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import com.creditease.agent.feature.monitoragent.datacatch.BaseMonitorDataCatchWorker; import com.creditease.agent.helpers.DataConvertHelper; import com.creditease.agent.helpers.jvmtool.JVMAgentInfo; import com.creditease.agent.spi.AbstractTimerWork; @@ -32,6 +34,8 @@ public class DetectorManager extends AbstractTimerWork { protected final Map detectorMap = new LinkedHashMap(); + + protected final Map workers = new ConcurrentHashMap(); public DetectorManager(String cName, String feature) { super(cName, feature); @@ -43,6 +47,8 @@ public void installDetector(BaseDetector detector) { return; } + detector.setWorkers(workers); + detectorMap.put(detector.getName(), detector); } diff --git a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/JVMContainerOSDetector.java b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/JVMContainerOSDetector.java index 172ae7e5..266baafc 100644 --- a/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/JVMContainerOSDetector.java +++ b/com.creditease.uav.agent/src/main/java/com/creditease/agent/feature/monitoragent/detect/JVMContainerOSDetector.java @@ -21,9 +21,12 @@ package com.creditease.agent.feature.monitoragent.detect; import java.util.Collection; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.Properties; +import com.creditease.agent.feature.monitoragent.datacatch.BaseMonitorDataCatchWorker; import com.creditease.agent.helpers.JSONHelper; import com.creditease.agent.helpers.StringHelper; import com.creditease.agent.helpers.jvmtool.JVMAgentInfo; @@ -55,6 +58,7 @@ private class ScanPingCallback implements HttpClientCallback { private OSProcess proc; public ScanPingCallback(OSProcess proc, String url) { + this.url = url; this.proc = proc; } @@ -115,6 +119,7 @@ private class GetSystemInfoCallback implements HttpClientCallback { private String vendor; public GetSystemInfoCallback(OSProcess proc, String url, String vendor) { + this.url = url; this.proc = proc; this.vendor = vendor; @@ -186,14 +191,17 @@ public void failed(HttpClientCallbackResult result) { protected String[] scanPorts = new String[0]; + protected String baseurl = "http://127.0.0.1"; + public JVMContainerOSDetector(String cName, String feature, String initHandlerKey, long detectInterval) { + super(cName, feature, initHandlerKey, detectInterval); String ports = this.getConfigManager().getFeatureConfiguration(this.feature, "detector.container.ports"); configScanPorts(ports); - client = HttpAsyncClientFactory.build(5, 100, 1, 1, 1); + client = HttpAsyncClientFactory.build(5, 100, 1000, 1000, 1000); } @Override @@ -211,7 +219,7 @@ private void scanWithConfigURLs() { for (String port : scanPorts) { - String baseurl = "http://127.0.0.1:" + port; + String baseurl = port.indexOf(":") == -1 ? "http://127.0.0.1:" + port : "http://" + port; client.doAsyncHttpGet(baseurl + UAV_MOF_ROOT + "jvm?action=ping", new ScanPingCallback(null, baseurl)); } @@ -276,23 +284,11 @@ private void scanWithProcDetection() { continue; } - for (String port : proc.getPorts()) { - String baseurl; - - /** - * option 1:ip:port - */ - if (port.indexOf(":") > -1) { - baseurl = "http://" + port; - } - /** - * option 2: port only - */ - else { - baseurl = "http://127.0.0.1:" + port; - } - - client.doAsyncHttpGet(baseurl + UAV_MOF_ROOT + "jvm?action=ping", new ScanPingCallback(proc, baseurl)); + List needDectectUrls=getDetectUrls(proc); + + for(String url: needDectectUrls) { + + client.doAsyncHttpGet(url + UAV_MOF_ROOT + "jvm?action=ping", new ScanPingCallback(proc, url)); } } } @@ -316,5 +312,66 @@ public void onConfigUpdate(Properties updatedConfig) { configScanPorts(ports); } } + + /** + * get urls which need detect + */ + private List getDetectUrls(OSProcess proc) { + + List urlList=new LinkedList(); + + for (String port : proc.getPorts()) { + + String url; + /** + * option 1:ip:port + */ + if (port.indexOf(":") > -1) { + url = "http://" + port; + } + /** + * option 2: port only + */ + else { + url = baseurl + ":" + port; + } + + if(workerExist(proc.getPid(),url,urlList)) { + return urlList; + } + } + + return urlList; + } + + /** + * check if the worker for this appServer exist + */ + public boolean workerExist(String pid,String url,List urlList) { + + String JVMAccessURL = url + UAV_MOF_ROOT; + + for(BaseMonitorDataCatchWorker worker:workers.values()) { + + JVMAgentInfo appServerInfo = jvmAgentInfos.get(worker.getName()); + + if(appServerInfo!=null && JVMAccessURL.equals((appServerInfo.getJVMAccessURL()))) { + + urlList.clear(); + + if(!pid.equals(appServerInfo.getId())) { + + // remove worker whose JVMAccessURL is the same but pid changes(usually restart) + removeWorker(worker.getName()); + + urlList.add(url); + } + return true; + } + } + + urlList.add(url); + return false; + } } diff --git a/com.creditease.uav.base/src/main/java/com/creditease/agent/profile/api/StandardProfileModeler.java b/com.creditease.uav.base/src/main/java/com/creditease/agent/profile/api/StandardProfileModeler.java index 234d1114..04523219 100644 --- a/com.creditease.uav.base/src/main/java/com/creditease/agent/profile/api/StandardProfileModeler.java +++ b/com.creditease.uav.base/src/main/java/com/creditease/agent/profile/api/StandardProfileModeler.java @@ -1005,6 +1005,10 @@ private void getJAXRSURLs(String jaxrsBaseUrl, Map> compServ Map compDesInfo = (Map) compInfo.get("anno"); Map annoWebService = (Map) compDesInfo.get("javax.ws.rs.Path"); + + if (annoWebService == null) { + continue; + } String resourceClassRelativePath = (String) annoWebService.get("value"); diff --git a/com.creditease.uav.collect/src/main/java/com/creditease/uav/collect/client/copylogagent/ReliableTaildirEventReader.java b/com.creditease.uav.collect/src/main/java/com/creditease/uav/collect/client/copylogagent/ReliableTaildirEventReader.java index 2befc66c..252e6b7a 100644 --- a/com.creditease.uav.collect/src/main/java/com/creditease/uav/collect/client/copylogagent/ReliableTaildirEventReader.java +++ b/com.creditease.uav.collect/src/main/java/com/creditease/uav/collect/client/copylogagent/ReliableTaildirEventReader.java @@ -182,6 +182,7 @@ else if (logPatternInfo2.getFlag() == StateFlag.EXIST) { } for (File f : files) { long inode = getInode(f); + removeInvalidTFInode(f, inode); TailFile tf = tailFiles.get(inode); if (tf == null || !tf.getPath().equals(f.getAbsolutePath())) { long startPos = skipToEnd ? f.length() : 0;// 第一次读取从头开始读 @@ -215,6 +216,19 @@ else if (logPatternInfo2.getFlag() == StateFlag.EXIST) { return updatedInodes; } + /** + * @param f + * @param inodeCurrent + */ + private void removeInvalidTFInode(File f, long inodeCurrent) { + for (Long inodeKey : tailFiles.keySet()) { + TailFile tf = tailFiles.get(inodeKey); + if (tf.getPath().equals(f.getAbsolutePath()) && inodeKey != inodeCurrent) { + tailFiles.remove(inodeKey); + } + } + } + private List getMatchFiles(File parentDir, final Pattern fileNamePattern) { FileFilter filter = new FileFilter() { @@ -427,28 +441,40 @@ public void loadPositions(String json) { inode = positionObject.getLong("inode"); pos = positionObject.getLong("pos"); file = positionObject.getString("file"); - // add line number - number = positionObject.getLongValue("num"); - for (Object v : Arrays.asList(inode, pos, file)) { - Preconditions.checkNotNull(v, "Detected missing value in position file. " + "inode: " + inode - + ", pos: " + pos + ", path: " + file); - } - TailFile tf = tailFiles.get(inode); + Long currentInode = 0L; try { - if (tf != null && tf.updatePos(file, inode, pos, number)) { - tailFiles.put(inode, tf); + currentInode = getInode(new File(file)); + } + catch (IOException e1) { + log.err(this, "TailFile updatePos FAILED,getInode Fail.", e1); + } + if (!currentInode.equals(inode)) { + maybeReloadMap.remove(inode); + } + else { + // add line number + number = positionObject.getLongValue("num"); + for (Object v : Arrays.asList(inode, pos, file)) { + Preconditions.checkNotNull(v, "Detected missing value in position file. " + "inode: " + inode + + ", pos: " + pos + ", path: " + file); } - else { - // add old tail file into memory - maybeReloadMap.put(inode, new Long[] { pos, number }); - if (log.isDebugEnable()) { - log.debug(this, "add old&inInterrupt file: " + file + ", inode: " + inode + ", pos: " + pos); + TailFile tf = tailFiles.get(inode); + try { + if (tf != null && tf.updatePos(file, inode, pos, number)) { + tailFiles.put(inode, tf); } + else { + // add old tail file into memory + maybeReloadMap.put(inode, new Long[] { pos, number }); + if (log.isDebugEnable()) { + log.debug(this, "add old&inInterrupt file: " + file + ", inode: " + inode + ", pos: " + pos); + } + } + } + catch (IOException e) { + log.err(this, "TailFile updatePos FAILED.", e); } - } - catch (IOException e) { - log.err(this, "TailFile updatePos FAILED.", e); } } } diff --git a/com.creditease.uav.console.buildComponent/config/web_pro.xml b/com.creditease.uav.console.buildComponent/config/web_pro.xml index 0ac9f88c..de80af5a 100644 --- a/com.creditease.uav.console.buildComponent/config/web_pro.xml +++ b/com.creditease.uav.console.buildComponent/config/web_pro.xml @@ -24,7 +24,15 @@ jersey-serlvet /rs/* + + + + apphubTimer + com.creditease.uav.timer.TimerServlet + 2 + + es-serlvet @@ -33,7 +41,7 @@ es.info {"forwar.url":"http://127.0.0.1:9200,http://127.0.0.1:9200"} - 2 + 3 true @@ -45,7 +53,7 @@ opentsdb-agent-servlet com.creditease.uav.opentsdb.OpenTSDBRestAgentServlet - 3 + 4 true @@ -62,7 +70,6 @@ /db2/ /db2/aggregators - @@ -110,10 +117,6 @@ uav.app.manage.redis.store.addr 127.0.0.1:26379 - - uav.app.ldap.redis.store.addr - 127.0.0.1:26379 - uav.app.godeye.redis.store.addr 127.0.0.1:26379 @@ -130,10 +133,6 @@ uav.app.manage.redis.store.params {"min":50,"max":300,"queue":10} - - uav.app.ldap.redis.store.params - {"min":30,"max":100,"queue":10} - uav.app.godeye.redis.store.params {"min":30,"max":100,"queue":5,"cacheaccess":5} @@ -204,7 +203,7 @@ uav.app.godeye.notify.mongodb.query.range - {"skip":0,"limit":20000} + {"skip":0,"limit":1000} uav.apphub.sso.admin.loginid @@ -212,7 +211,7 @@ uav.apphub.sso.admin.password - Uav!630admin + 123456 uav.apphub.sso.guest.loginid @@ -228,7 +227,7 @@ uav.apphub.sso.ldap.connection.info - {"url":"ldap://127.0.0.1:389/","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} + {"url":"ldap://127.0.0.1:389/","timeout":"1000","retry":"5","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} uav.apphub.sso.grafana.connection.info diff --git a/com.creditease.uav.console.buildComponent/config/web_test.xml b/com.creditease.uav.console.buildComponent/config/web_test.xml index 1635f791..4238f9e4 100644 --- a/com.creditease.uav.console.buildComponent/config/web_test.xml +++ b/com.creditease.uav.console.buildComponent/config/web_test.xml @@ -24,7 +24,15 @@ jersey-serlvet /rs/* + + + + apphubTimer + com.creditease.uav.timer.TimerServlet + 2 + + es-serlvet @@ -33,7 +41,7 @@ es.info {"forwar.url":"http://127.0.0.1:9200,http://127.0.0.1:9200"} - 2 + 3 true @@ -45,7 +53,7 @@ opentsdb-agent-servlet com.creditease.uav.opentsdb.OpenTSDBRestAgentServlet - 3 + 4 true @@ -62,7 +70,6 @@ /db2/ /db2/aggregators - @@ -110,10 +117,6 @@ uav.app.manage.redis.store.addr 127.0.0.1:6379 - - uav.app.ldap.redis.store.addr - 127.0.0.1:6379 - uav.app.godeye.redis.store.addr 127.0.0.1:6379 @@ -130,10 +133,6 @@ uav.app.manage.redis.store.params {"min":50,"max":300,"queue":10,"pwd":"Uav!1227Admin"} - - uav.app.ldap.redis.store.params - {"min":30,"max":100,"queue":5,"pwd":"Uav!1227Admin"} - uav.app.godeye.redis.store.params {"min":30,"max":100,"queue":5,"cacheaccess":5,"pwd":"Uav!1227Admin"} @@ -209,7 +208,7 @@ uav.app.godeye.notify.mongodb.query.range - {"skip":0,"limit":20000} + {"skip":0,"limit":1000} uav.apphub.sso.admin.loginid @@ -217,7 +216,7 @@ uav.apphub.sso.admin.password - Uav!1227admin + 123456 uav.apphub.sso.guest.loginid @@ -233,7 +232,7 @@ uav.apphub.sso.ldap.connection.info - {"url":"ldap://127.0.0.1:389/","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} + {"url":"ldap://127.0.0.1:389/","timeout":"1000","retry":"5","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} uav.apphub.sso.grafana.connection.info diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/filter/SessionAsyncFilter.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/filter/SessionAsyncFilter.java index 62acaaf9..21cdf631 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/filter/SessionAsyncFilter.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/filter/SessionAsyncFilter.java @@ -56,7 +56,7 @@ public class SessionAsyncFilter implements Filter { private String[] exResSs; private ISystemLogger logger = null; - private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); @Override public void init(FilterConfig filterConfig) throws ServletException { @@ -248,7 +248,7 @@ private void userLoggerInfo(HttpServletRequest request) { */ String ip = request.getRemoteAddr(); - String xip = request.getHeader("X-Forward-For"); + String xip = request.getHeader("X-Forwarded-For"); String time = sdf.format(new Date()); String userid = getUserIdBySession(request); diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/rest/GUIService.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/rest/GUIService.java index 930f8e4d..f60efc97 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/rest/GUIService.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/rest/GUIService.java @@ -31,11 +31,13 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import javax.inject.Singleton; import javax.servlet.http.HttpServletRequest; @@ -50,6 +52,7 @@ import javax.ws.rs.container.Suspended; import javax.ws.rs.core.MediaType; +import com.creditease.agent.helpers.EncryptionHelper; import com.creditease.agent.helpers.IOHelper; import com.creditease.agent.helpers.JSONHelper; import com.creditease.agent.helpers.NetworkHelper; @@ -138,9 +141,17 @@ public void init() { try { /** - * redis cache init :等待AppHubInit执行完成(0.5秒为估计值) + * redis cache init :等待AppHubInit执行完成(1秒为估计值) + */ + Thread.sleep(1000L); + /** + * 先清空redis:app group 授权信息 + */ + cm.del("apphub.gui.cache", "manage.app"); + cm.del("apphub.gui.cache", "manage.group"); + /** + * 然后将mongodb数据缓存到redis */ - Thread.sleep(500L); createGroupInfoCache(); createAppInfoCache(); } @@ -214,10 +225,10 @@ else if (loginRegister(loginId, loginPwd, request)) { monitor.flushToSystemProperties(); String ip = request.getRemoteAddr(); - String xip = request.getHeader("X-Forward-For"); + String xip = request.getHeader("X-Forwarded-For"); String userip = getClientIP(ip, xip); Map userInfo = new HashMap(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); String time = sdf.format(new Date()); userInfo.put("key", "ulog"); userInfo.put("time", time); @@ -257,10 +268,10 @@ public void loginOut() { Object obj = request.getSession(false).getAttribute("apphub.gui.session.login.user.id"); String userId = null == obj ? "" : String.valueOf(obj); String ip = request.getRemoteAddr(); - String xip = request.getHeader("X-Forward-For"); + String xip = request.getHeader("X-Forwarded-For"); String userip = getClientIP(ip, xip); Map userInfo = new HashMap(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); String time = sdf.format(new Date()); userInfo.put("key", "ulog"); userInfo.put("time", time); @@ -326,29 +337,72 @@ public String loadMainMenu() throws IOException { * * @return */ + @SuppressWarnings("rawtypes") @GET @Path("loadUserManageInfo") @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") public void loadUserManageInfo(@Suspended AsyncResponse response) { - String result = ""; String userGroup = String .valueOf(request.getSession(false).getAttribute("apphub.gui.session.login.user.group")); Map manageGroup = cm.getHashAll("apphub.gui.cache", "manage.group"); - // 授权匹配 - if (manageGroup.containsKey(userGroup)) { + /** + * 获取用户ldap信息 begin + */ + GUISSOClient guissoClient = GUISSOClientFactory.getGUISSOClient(request); + String userLoginId = String.valueOf(request.getSession(false).getAttribute("apphub.gui.session.login.user.id")); + Object userLdapInfo = guissoClient.getUserByQuery(userLoginId); + String userLdapInfoStr = JSONHelper.toString(userLdapInfo); + /** + * 获取用户ldap信息 end + */ + + /** + * 获取匹配授权信息,去重 + * + * 只要匹配上,权限都能得到 + */ + Set appids = new HashSet(); + Iterator manageGroupI = manageGroup.keySet().iterator(); + while (manageGroupI.hasNext()) { + String key = String.valueOf(manageGroupI.next()); + String[] keys = key.split(","); + String groupId = keys[0].replace("groupId:", ""); + String ldapKey = keys[1].replace("ldappKey:", ""); + + boolean keyCheck = false; + if (ldapKey.length() == 0) { + keyCheck = true; // 没有则不验证 + } + else { + keyCheck = userLdapInfoStr.contains(ldapKey); // 关键字匹配 + } + + if (userGroup.equals(groupId) && keyCheck) { + // 授权匹配 + String[] userManAppids = manageGroup.get(key).split(","); + for (String appid : userManAppids) { + appids.add(appid); + } + } + } + + String result = ""; + if (appids.size() > 0) { + // 赋值 + Iterator appidsI = appids.iterator(); Map userManageInfo = new HashMap(); - String[] userManAppids = manageGroup.get(userGroup).split(","); - for (String appid : userManAppids) { + while (appidsI.hasNext()) { + String appid = String.valueOf(appidsI.next()); Map appinfo = cm.getHash("apphub.gui.cache", "manage.app", appid); userManageInfo.putAll(appinfo); } + result = JSONHelper.toString(userManageInfo); } - logger.info(this, "\r\nloadUserManageInfo\r\nuserGroup:" + userGroup + "\r\nmanageGroup:" + manageGroup - + " \r\nresult:" + result); + logger.info(this, "\r\nloadUserManageInfo->\r\nuserGroup:" + userGroup + "\r\nmapping:" + appids.toString()); response.resume(result); @@ -366,7 +420,45 @@ public void createValidataCode() throws Exception { CaptchaTools vcTools = new CaptchaTools(); vcTools.newVC(request.getSession(), response.getOutputStream()); } + + /** + * 获取apphub相关信息,并且经行AES CBC加密 + * + * 目前封装信息有:用户信息 + * + * @return + */ + @GET + @Path("loadApphubInfoByAES") + @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") + public String loadApphubInfoByAES() throws IOException { + + HttpSession session = request.getSession(false); + Object userId = null == session ? null : session.getAttribute("apphub.gui.session.login.user.id"); + Map apphubInfo = new HashMap(); + if (null != userId) { + Object userGroup = null == session ? null : session.getAttribute("apphub.gui.session.login.user.group"); + Object emailList = null == session ? null : session.getAttribute("apphub.gui.session.login.user.emailList"); + Object emailAuthList = null == session ? null + : session.getAttribute("apphub.gui.session.login.user.authorize.emailList"); + Object systemAuthList = null == session ? null + : session.getAttribute("apphub.gui.session.login.user.authorize.systems"); + + apphubInfo.put("userId", String.valueOf(userId)); + apphubInfo.put("groupId", String.valueOf(userGroup)); + apphubInfo.put("emailList", String.valueOf(emailList)); + apphubInfo.put("emailAuthList", String.valueOf(emailAuthList)); + apphubInfo.put("systemAuthList", String.valueOf(systemAuthList)); + apphubInfo.put("timeStamp", String.valueOf(new Date().getTime())); + + } + String strMsg = JSONHelper.toString(apphubInfo); + String resultStr = EncryptionHelper.encryptByAesCBC(strMsg, "UavappHubaEs_keY", false, "UavappHubaEs_keY", + "utf-8"); + return createResponeJson(RespCode.SUCCESS, "", resultStr); + } + // ------------------------------------------------以下为api支持-----------------------------------------------------------> /** @@ -456,13 +548,11 @@ private void whiteListFilter(String loginId, Map userInfo) { * @return */ private boolean whiteListSet(String loginId, String groupName, Map userInfo) { - - String checkLoginId = loginId; - + boolean result = false; String[] memberNames = whiteList.get(groupName).split(","); for (String memberName : memberNames) { - if (checkLoginId.equals(memberName)) { + if (loginId.toLowerCase().equals(memberName.toLowerCase())) { userInfo.remove("groupId"); userInfo.put("groupId", groupName); result = true; @@ -629,8 +719,11 @@ public void completed(HttpClientCallbackResult result) { Map respMap = JSONHelper.toObject(respStr, Map.class); List> respList = (List>) respMap.get("data"); for (Map map : respList) { - String key = map.get("groupid"); + String groupid = map.get("groupid"); String value = map.get("appids"); + String ldapkey = map.get("ldapkey") == null ? "" : map.get("ldapkey"); + + String key = "groupId:" + groupid + ",ldappKey:" + ldapkey; groupCache.put(key, value); } cm.putHash("apphub.gui.cache", "manage.group", groupCache); diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOClient.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOClient.java index fff8ff44..e44ecbf6 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOClient.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOClient.java @@ -51,7 +51,6 @@ public GUISSOClient(HttpServletRequest request) { initMessageMD5(); initSystemUser(request); - initRedis(request); } @@ -61,22 +60,8 @@ public Map getUserByLogin(String loginId, String loginPwd) { userInfo = getUserBySystem(loginId, loginPwd); - if (userInfo.isEmpty()) { - userInfo = getUserByCache(loginId, loginPwd); - } - if (userInfo.isEmpty()) { userInfo = getUserByLoginImpl(loginId, loginPwd); - if (!userInfo.isEmpty()) { - userInfo.put("loginPwd", bytes2Hex(md.digest(loginPwd.getBytes()))); - cm.putJSON("apphub.ldap.cache", loginId, userInfo, 7L, TimeUnit.DAYS); - loggerInfo("用户信息缓存 ", "保存7天", "成功", loginId); - } - } - - if (!userInfo.isEmpty()) { - userInfo.remove("loginPwd"); - loggerInfo("用户登录 ", "信息获取", "成功", userInfo.toString()); } return userInfo; @@ -160,21 +145,6 @@ private void initSystemUser(HttpServletRequest request) { } - @SuppressWarnings("unchecked") - private void initRedis(HttpServletRequest request) { - - if (null == cm) { - String redisAddrStr = request.getServletContext().getInitParameter("uav.app.ldap.redis.store.addr"); - Map redisParamsMap = JSONHelper.toObject( - request.getServletContext().getInitParameter("uav.app.ldap.redis.store.params"), Map.class); - cm = CacheManagerFactory.build(redisAddrStr, Integer.valueOf(String.valueOf(redisParamsMap.get("min"))), - Integer.valueOf(String.valueOf(redisParamsMap.get("max"))), - Integer.valueOf(String.valueOf(redisParamsMap.get("queue"))), - String.valueOf(redisParamsMap.get("pwd"))); - } - - } - private Map getUserBySystem(String loginId, String loginPwd) { Map result = new HashMap(); @@ -186,44 +156,9 @@ private Map getUserBySystem(String loginId, String loginPwd) { } } - if (!result.isEmpty()) { - loggerInfo("系统用户 ", "校验", "成功", loginId); - } - return result; } - @SuppressWarnings("unchecked") - private Map getUserByCache(String loginId, String loginPwd) { - - Map result = new HashMap(); - - if (cm.exists("apphub.ldap.cache", loginId)) { - Map cache = cm.getJSON("apphub.ldap.cache", loginId, Map.class); - if (bytes2Hex(md.digest(loginPwd.getBytes())).equals(cache.get("loginPwd"))) { - result = cache; - } - } - - if (!result.isEmpty()) { - loggerInfo("缓存用户 ", "校验", "成功", loginId); - } - return result; - - } - - private String bytes2Hex(byte[] bys) { - - char[] chs = new char[bys.length * 2]; - int stopCondition = bys.length; - int offset = 0; - for (int i = 0; i < stopCondition; i++) { - chs[offset++] = hex[bys[i] >> 4 & 0xf]; - chs[offset++] = hex[bys[i] & 0xf]; - } - return new String(chs); - } - protected void loggerInfo(String title, String action, String result, String msg) { logger.info(this, title + "[" + action + "]" + result + " " + msg); diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOLdapClient.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOLdapClient.java index e28e8a57..4940783b 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOLdapClient.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/apphub/sso/GUISSOLdapClient.java @@ -85,11 +85,21 @@ private void initLdapParams(String action) { String ldapConUrl = ldapConfig.get("url"); String ldapConUser = ldapConfig.get("user"); String ldapConPassWord = ldapConfig.get("password"); + String ldapTimeout = ldapConfig.get("timeout"); param.put(Context.PROVIDER_URL, ldapConUrl + ldapConBasedn); param.put(Context.SECURITY_PRINCIPAL, ldapConUser); param.put(Context.SECURITY_CREDENTIALS, ldapConPassWord); param.put(Context.SECURITY_AUTHENTICATION, "simple"); param.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + param.put("com.sun.jndi.ldap.connect.timeout", ldapTimeout); + param.put("com.sun.jndi.ldap.read.timeout", ldapTimeout); + + /** + * ldap以下字段转码需要特殊处理:不显示乱码,但也不会显示为可识别的string,以binary string显示 + */ + param.put("java.naming.ldap.attributes.binary", + "msExchMailboxGuid objectSid objectGUID msExchMailboxSecurityDescriptor "); + ldapParams.put(action, param); } @@ -146,32 +156,46 @@ private boolean ldapApiCheck(String loginId, String password) { boolean result = false; String action = "login"; + LdapContext newContext = null; try { initLdapContext(action); - LdapContext ldapCtx = ldapContexts.get(action); + Properties actionParam = ldapParams.get(action); - ldapCtx.addToEnvironment(Context.SECURITY_PRINCIPAL, loginId); - ldapCtx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); + // 替换参数,账号密码验证 + actionParam.put(Context.SECURITY_PRINCIPAL, loginId); + actionParam.put(Context.SECURITY_CREDENTIALS, password); // 密码验证,不报错则为验证成功 - ldapCtx.reconnect(null); + newContext = new InitialLdapContext(actionParam, null); result = true; - loggerInfo("LDAP信息", "校验", "成功", loginId); + loggerInfo("LDAP信息", "登陆校验", "成功", loginId); } catch (AuthenticationException e) { - // 此异常为用户验证失败,因此不做ldapContext清除 - loggerError("LDAP信息校验", loginId + " (业务意义为验证失败,异常信息可以忽略)", e); + // 此异常为用户验证失败 + loggerInfo("LDAP信息", "登陆校验", "失败", loginId); } catch (Exception e1) { loggerError("LDAP信息校验", loginId, e1); clearLdapContext(action); } + finally { + + try { + if (null != newContext) { + newContext.close(); + } + } + catch (NamingException e) { + loggerError("LDAP信息校验,链接关闭", loginId, e); + } + } return result; } - private List ldapApiQuery(String action, String name, String filter) { + private List ldapApiQuery(String name, String filter) { + String action = "query"; String logMsg = action + " " + filter; List result = new ArrayList(); try { @@ -180,6 +204,7 @@ private List ldapApiQuery(String action, String name, String filte SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); + NamingEnumeration en = ldapCtx.search(name, filter, constraints); // means all nodes @@ -230,20 +255,29 @@ protected Map getUserByLoginImpl(String loginId, String password return Collections.emptyMap(); } - String action = "login"; String filter = primaryKey + "=" + loginId; - List sResultList = ldapApiQuery(action, "", filter); - // filter userPrincipalName= 只能查询到一个结果 - SearchResult sResult = sResultList.get(0); + int retry = Integer.parseInt(ldapConfig.get("retry")); + List sResultList = new ArrayList(); + do { + sResultList = ldapApiQuery("", filter); + retry--; + } + while ((sResultList.isEmpty() && retry > 0)); + + Map result = new HashMap(); + if (!sResultList.isEmpty()) { + + // filter userPrincipalName= 只能查询到一个结果 + SearchResult sResult = sResultList.get(0); - String groupIdStr = formatGroupId(sResult); - String emailListStr = formatEmailList(sResult); + String groupIdStr = formatGroupId(sResult); + String emailListStr = formatEmailList(sResult); - Map result = new HashMap(); - result.put("loginId", loginId); - result.put("groupId", groupIdStr); - result.put("emailList", emailListStr); + result.put("loginId", loginId); + result.put("groupId", groupIdStr); + result.put("emailList", emailListStr); + } return result; } @@ -265,13 +299,12 @@ public List> getUserByQuery(String email) { String filter = "(|(" + userCNField + "=" + email + ")(" + userQueryField + "=" + email + ")(" + userQueryField + "=" + email1 + "))"; - - String action = "query"; + /** * 查询ldap 获取list信息 */ List> result = new ArrayList>(); - List sResultList = ldapApiQuery(action, "", filter); + List sResultList = ldapApiQuery("", filter); if (sResultList.isEmpty()) { Map msg = new HashMap(); msg.put("msg", "email query,result is empty."); @@ -283,13 +316,12 @@ public List> getUserByQuery(String email) { /** * 遍历格式化用户信息 */ - Map emailInfoMap = formatEmailInfo(sResult, userQueryField); String groupIdStr = formatGroupId(sResult); String emailListStr = formatEmailList(sResult); + Map emailInfoMap = formatEmailInfo(sResult, userQueryField); Map info = new HashMap(); - info.put("email", emailInfoMap.get("email")); - info.put("name", emailInfoMap.get("name")); + info.putAll(emailInfoMap); info.put("groupId", groupIdStr); info.put("emailList", emailListStr); @@ -307,7 +339,6 @@ public List> getUserByQuery(String email) { public Map getEmailListByQuery(String email) { Map result = new LinkedHashMap(); - String action = "query"; String filter = ""; String suffix = ldapConfig.get("suffix"); try { @@ -320,7 +351,7 @@ public Map getEmailListByQuery(String email) { filter = "(|(" + groupCNField + "=" + email + ")(" + groupQueryField + "=" + email + ")(" + groupQueryField + "=" + email1 + "))"; - List sResultList = ldapApiQuery(action, "", filter); + List sResultList = ldapApiQuery("", filter); // filter 只能查询到一个结果 SearchResult sResult = sResultList.get(0); if (null == sResult) { @@ -346,7 +377,7 @@ public Map getEmailListByQuery(String email) { } catch (Exception e) { - clearLdapContext(action); + clearLdapContext("query"); logger.err(this, e.getMessage(), e); } return result; @@ -481,6 +512,8 @@ private Map formatEmailInfo(SearchResult sResult, String targetK if ("cn".equals(attrId)) { result.put("name", attrValue); } + + result.put(attrId, attrValue); } } diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/APMRestService.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/APMRestService.java index 7ffccc73..50b544d3 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/APMRestService.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/APMRestService.java @@ -21,6 +21,7 @@ package com.creditease.uav.godeye.rest; import java.io.InputStream; +import java.util.Map; import javax.inject.Singleton; import javax.ws.rs.POST; @@ -32,6 +33,7 @@ import org.apache.http.HttpStatus; +import com.creditease.agent.helpers.StringHelper; import com.creditease.agent.http.api.UAVHttpMessage; import com.creditease.uav.httpasync.HttpClientCallback; import com.creditease.uav.httpasync.HttpClientCallbackResult; @@ -86,6 +88,25 @@ public void queryIVC(String data, @Suspended AsyncResponse response) { UAVHttpMessage msg = new UAVHttpMessage(data); + Map request = msg.getRequest(); + String content = request.get("content"); + + if (!StringHelper.isEmpty(content)) { + String[] contents = content.split(","); + String[] condition; + for (String ctn : contents) { + if(StringHelper.isEmpty(ctn)) { + continue; + } + condition = ctn.split("="); + if(condition.length < 2) { + response.resume("{\"rs\":\"ERR\",\"msg\":\"query syntax error\"}"); + return; + } + request.put(condition[0], condition[1].replaceAll("\"", "")); + } + } + this.doHttpPost("uav.app.apm.ivc.http.addr", "/ivc/q", msg, new IVCCallback(response)); } diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/GodEyeRestService.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/GodEyeRestService.java index 3710dad8..3f3fedd8 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/GodEyeRestService.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/godeye/rest/GodEyeRestService.java @@ -1441,14 +1441,11 @@ else if ("ALL".equals(groups)) { sortMap.put("sort", sort); list.add(sortMap); - HashMap skipMap = new HashMap(); - skipMap.put("skip", mongodbQueryRangeMap.get("skip")); - list.add(skipMap); - - HashMap limitMap = new HashMap(); - limitMap.put("limit", mongodbQueryRangeMap.get("limit")); - list.add(limitMap); - // 过滤数据,只查询最近的指定数据 end + HashMap firstRecord = new HashMap(); + firstRecord.put("firstrecord", "true"); + HashMap firstRecordMatch = new HashMap(); + firstRecordMatch.put("match", firstRecord); + list.add(firstRecordMatch); // 封装组合查询条件 if (jsonParam.containsKey("search")) { @@ -1469,11 +1466,14 @@ else if ("ALL".equals(groups)) { list.addAll(groupList); } - HashMap firstRecord = new HashMap(); - firstRecord.put("firstrecord", "true"); - HashMap firstRecordMatch = new HashMap(); - firstRecordMatch.put("match", firstRecord); - list.add(firstRecordMatch); + HashMap skipMap = new HashMap(); + skipMap.put("skip", mongodbQueryRangeMap.get("skip")); + list.add(skipMap); + + HashMap limitMap = new HashMap(); + limitMap.put("limit", mongodbQueryRangeMap.get("limit")); + list.add(limitMap); + // 过滤数据,只查询最近的指定数据 end HashMap pageIndex = new HashMap(); HashMap pageSize = new HashMap(); @@ -1553,13 +1553,13 @@ else if ("ALL".equals(groups)) { sortMap.put("sort", sort); list.add(sortMap); - HashMap skipMap = new HashMap(); - skipMap.put("skip", mongodbQueryRangeMap.get("skip")); - list.add(skipMap); + HashMap requestParam = new HashMap(); + HashMap firstRecord = new HashMap(); + HashMap firstRecordMatch = new HashMap(); + firstRecord.put("firstrecord", "true"); + firstRecordMatch.put("match", firstRecord); + list.add(firstRecordMatch); - HashMap limitMap = new HashMap(); - limitMap.put("limit", mongodbQueryRangeMap.get("limit")); - list.add(limitMap); // 过滤数据,只查询最近的指定数据 end // 封装组合查询条件 @@ -1581,13 +1581,15 @@ else if ("ALL".equals(groups)) { list.addAll(groupList); } - HashMap requestParam = new HashMap(); - HashMap firstRecord = new HashMap(); - HashMap firstRecordMatch = new HashMap(); - firstRecord.put("firstrecord", "true"); - firstRecordMatch.put("match", firstRecord); + HashMap skipMap = new HashMap(); + skipMap.put("skip", mongodbQueryRangeMap.get("skip")); + list.add(skipMap); + + HashMap limitMap = new HashMap(); + limitMap.put("limit", mongodbQueryRangeMap.get("limit")); + list.add(limitMap); + requestParam.put("count", "true"); - list.add(firstRecordMatch); list.add(requestParam); // 封装http请求数据 @@ -1667,6 +1669,14 @@ public void noitifyEvent(@Suspended AsyncResponse response) throws Exception { sort.put("sortorder", "-1"); sortMap.put("sort", sort); list.add(sortMap); + + // modify start : 只返回firstrecord为true的事件id + HashMap firstRecord = new HashMap(); + HashMap firstRecordMatch = new HashMap(); + firstRecord.put("firstrecord", "true"); + firstRecordMatch.put("match", firstRecord); + list.add(firstRecordMatch); + // modify end HashMap skipMap = new HashMap(); skipMap.put("skip", mongodbQueryRangeMap.get("skip")); @@ -1677,14 +1687,6 @@ public void noitifyEvent(@Suspended AsyncResponse response) throws Exception { list.add(limitMap); // 过滤数据,只查询最近的指定数据 end - // modify start : 只返回firstrecord为true的事件id - HashMap firstRecord = new HashMap(); - HashMap firstRecordMatch = new HashMap(); - firstRecord.put("firstrecord", "true"); - firstRecordMatch.put("match", firstRecord); - list.add(firstRecordMatch); - // modify end - list.add(requestParam); // 封装http请求数据 @@ -1753,13 +1755,12 @@ else if ("ALL".equals(groups)) { sortMap.put("sort", sort); list.add(sortMap); - HashMap skipMap = new HashMap(); - skipMap.put("skip", mongodbQueryRangeMap.get("skip")); - list.add(skipMap); + HashMap firstRecord = new HashMap(); + HashMap firstRecordMatch = new HashMap(); + firstRecord.put("firstrecord", "true"); + firstRecordMatch.put("match", firstRecord); + list.add(firstRecordMatch); - HashMap limitMap = new HashMap(); - limitMap.put("limit", mongodbQueryRangeMap.get("limit")); - list.add(limitMap); // 过滤数据,只查询最近的指定数据 end // 封装组合查询条件 list.add = and @@ -1829,18 +1830,19 @@ else if ("ALL".equals(groups)) { list.addAll(groupList); } - HashMap firstRecord = new HashMap(); - HashMap firstRecordMatch = new HashMap(); + HashMap skipMap = new HashMap(); + skipMap.put("skip", mongodbQueryRangeMap.get("skip")); + list.add(skipMap); + + HashMap limitMap = new HashMap(); + limitMap.put("limit", mongodbQueryRangeMap.get("limit")); + list.add(limitMap); + HashMap pageIndex = new HashMap(); HashMap pageSize = new HashMap(); HashMap pageSortOrder = new HashMap(); - firstRecord.put("firstrecord", "true"); - firstRecordMatch.put("match", firstRecord); pageIndex.put("pageindex", String.valueOf(jsonParam.get("pageindex"))); pageSize.put("pagesize", String.valueOf(jsonParam.get("pagesize"))); - - list.add(firstRecordMatch); - list.add(sortMap); list.add(pageIndex); list.add(pageSize); list.add(pageSortOrder); @@ -1912,13 +1914,13 @@ else if ("ALL".equals(groups)) { sortMap.put("sort", sort); list.add(sortMap); - HashMap skipMap = new HashMap(); - skipMap.put("skip", mongodbQueryRangeMap.get("skip")); - list.add(skipMap); + HashMap requestParam = new HashMap(); + HashMap firstRecord = new HashMap(); + HashMap firstRecordMatch = new HashMap(); + firstRecord.put("firstrecord", "true"); + firstRecordMatch.put("match", firstRecord); + list.add(firstRecordMatch); - HashMap limitMap = new HashMap(); - limitMap.put("limit", mongodbQueryRangeMap.get("limit")); - list.add(limitMap); // 过滤数据,只查询最近的指定数据 end // 封装组合查询条件 list.add = and @@ -1988,13 +1990,15 @@ else if ("ALL".equals(groups)) { list.addAll(groupList); } - HashMap requestParam = new HashMap(); - HashMap firstRecord = new HashMap(); - HashMap firstRecordMatch = new HashMap(); - firstRecord.put("firstrecord", "true"); - firstRecordMatch.put("match", firstRecord); + HashMap skipMap = new HashMap(); + skipMap.put("skip", mongodbQueryRangeMap.get("skip")); + list.add(skipMap); + + HashMap limitMap = new HashMap(); + limitMap.put("limit", mongodbQueryRangeMap.get("limit")); + list.add(limitMap); + requestParam.put("count", "true"); - list.add(firstRecordMatch); list.add(requestParam); // 封装http请求数据 @@ -2130,9 +2134,9 @@ public void doNodeCtrlOperation(String data, @Suspended AsyncResponse response) if (isCheckNodeOperSecurity == true) { Long ts = (Long) session.getAttribute("apphub.godeye.node.oper." + nodeUrl + ".timeout"); - if (ts != null && timeStamp - ts < 60000 && (!"loadnodepro".equalsIgnoreCase(msg.getIntent()) + if (ts != null && timeStamp - ts < 3000 && (!"loadnodepro".equalsIgnoreCase(msg.getIntent()) && !"chgsyspro".equalsIgnoreCase(msg.getIntent()))) { - response.resume("{\"rs\":\"ERR\",\"msg\":\"该节点操作1分钟内只能操作一次\"}"); + response.resume("{\"rs\":\"ERR\",\"msg\":\"该节点操作3秒内只能操作一次\"}"); return; } @@ -2142,7 +2146,7 @@ public void doNodeCtrlOperation(String data, @Suspended AsyncResponse response) } String ip = request.getRemoteAddr(); - String xip = request.getHeader("X-Forward-For"); + String xip = request.getHeader("X-Forwarded-For"); ip = getClientIP(ip, xip); msg.getRequest().put("uid", uid); diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/ManageRestService.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/ManageRestService.java index feb935bd..a55c3c75 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/ManageRestService.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/ManageRestService.java @@ -121,7 +121,7 @@ public void loadAppByid(AppEntity appEntity, @Suspended AsyncResponse response) data.put("where", where); Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); - Map callBackInput = createInput(null, null, "query"); + Map callBackInput = createAppInput(null, null, "query"); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); } @@ -152,7 +152,7 @@ public void loadApps(AppEntity appEntity, @Suspended AsyncResponse response) { data.put("sort", sort); Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); - Map callBackInput = createInput(null, null, "query"); + Map callBackInput = createAppInput(null, null, "query"); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); } @@ -170,23 +170,40 @@ public void loadAllApps(@Suspended AsyncResponse response) { data.put("sort", sort); Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); - Map callBackInput = createInput(null, null, "query"); + Map callBackInput = createAppInput(null, null, "query"); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); } + @POST + @Path("loadGroupByInfo") + public void loadGroupByInfo(GroupEntity groupEntity, @Suspended AsyncResponse response) { + + Map where = new HashMap(); + where.put("groupid", groupEntity.getGroupid()); + where.put("ldapkey", groupEntity.getLdapkey()); + where.put("state", 1); + + Map data = new HashMap(); + data.put("where", where); + + Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); + Map callBackInput = createGroupInput(null, null, null, "query"); + manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); + } + @POST @Path("loadGroupByid") public void loadGroupByid(GroupEntity groupEntity, @Suspended AsyncResponse response) { Map where = new HashMap(); - where.put("groupid", groupEntity.getGroupid()); + where.put("_id", groupEntity.getId()); where.put("state", 1); Map data = new HashMap(); data.put("where", where); Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); - Map callBackInput = createInput(null, null, "query"); + Map callBackInput = createGroupInput(null, null, null, "query"); manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); } @@ -216,7 +233,7 @@ public void loadAllGroups(GroupEntity groupEntity, @Suspended AsyncResponse resp data.put("sort", sort); Map jsonRequest = createHttpMapRequest(bussinessTypeQuery, data); - Map callBackInput = createInput(null, null, "query"); + Map callBackInput = createGroupInput(null, null, null, "query"); manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); } @@ -228,17 +245,17 @@ public void loadCount(String paramVlue, @Suspended AsyncResponse response) { String coulum = null; String mType = null; ManageHttpClientCallback messageCallBack = null; - Map callBackInput = createInput(null, null, "query"); Map obj = JSONHelper.toObject(paramVlue, Map.class); String type = (String) obj.get("type"); if ("APP".equals(type)) { coulum = "appurl"; mType = manageTypeApp; - messageCallBack = new AppHttpCallBack(response, callBackInput); + messageCallBack = new AppHttpCallBack(response, createAppInput(null, null, "query")); } else if ("GROUP".equals(type)) { coulum = "groupid"; mType = manageTypeGroup; + Map callBackInput = createGroupInput(null, null, null, "query"); messageCallBack = new GroupHttpCallBack(response, callBackInput); } Map regex = new HashMap(); @@ -276,7 +293,7 @@ public void addApp(AppEntity appEntity, @Suspended AsyncResponse response) throw data.put("operationuser", request.getSession(false).getAttribute("apphub.gui.session.login.user.id")); Map jsonRequest = createHttpMapRequest(bussinessTypeCreate, data); - Map callBackInput = createInput(id, appurl, "create"); + Map callBackInput = createAppInput(id, appurl, "create"); callBackInput.put("configpath", configpath); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); @@ -287,10 +304,12 @@ public void addApp(AppEntity appEntity, @Suspended AsyncResponse response) throw public void addGroup(GroupEntity groupEntity, @Suspended AsyncResponse response) throws Exception { String groupId = XSSFilter(groupEntity.getGroupid()); + String ldapkey = XSSFilter(groupEntity.getLdapkey()); String appIds = XSSFilter(groupEntity.getAppids()); String time = df.format(new Date()); Map data = new HashMap(); data.put("groupid", groupId); + data.put("ldapkey", ldapkey); data.put("appids", appIds); data.put("state", 1); data.put("createtime", time); @@ -298,7 +317,7 @@ public void addGroup(GroupEntity groupEntity, @Suspended AsyncResponse response) data.put("operationuser", request.getSession(false).getAttribute("apphub.gui.session.login.user.id")); Map jsonRequest = createHttpMapRequest(bussinessTypeCreate, data); - Map callBackInput = createInput(groupId, appIds, "create"); + Map callBackInput = createGroupInput(groupId, ldapkey, appIds, "create"); manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); } @@ -325,7 +344,7 @@ public void updateApp(AppEntity appEntity, @Suspended AsyncResponse response) th modify.put("update", update); Map jsonRequest = createHttpMapRequest(bussinessTypeModify, modify); - Map callBackInput = createInput(id, newurl, "modify"); + Map callBackInput = createAppInput(id, newurl, "modify"); callBackInput.put("configpath", configpath); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); } @@ -334,11 +353,13 @@ public void updateApp(AppEntity appEntity, @Suspended AsyncResponse response) th @Path("updateGroup") public void updateGroup(GroupEntity groupEntity, @Suspended AsyncResponse response) throws Exception { + String id = XSSFilter(groupEntity.getId()); String groupId = XSSFilter(groupEntity.getGroupid()); + String ldapKey = XSSFilter(groupEntity.getLdapkey()); String appIds = XSSFilter(groupEntity.getAppids()); String time = df.format(new Date()); Map where = new HashMap(); - where.put("groupid", groupId); + where.put("_id", id); Map cloumns = new HashMap(); cloumns.put("operationtime", time); @@ -352,7 +373,7 @@ public void updateGroup(GroupEntity groupEntity, @Suspended AsyncResponse respon data.put("where", where); data.put("update", set); Map jsonRequest = createHttpMapRequest(bussinessTypeModify, data); - Map callBackInput = createInput(groupEntity.getGroupid(), appIds, "modify"); + Map callBackInput = createGroupInput(groupId, ldapKey, appIds, "modify"); manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); } @@ -376,7 +397,7 @@ public void delApp(AppEntity appEntity, @Suspended AsyncResponse response) throw modify.put("update", update); Map jsonRequest = createHttpMapRequest(bussinessTypeModify, modify); - Map callBackInput = createInput(appEntity.getAppid(), null, "delete"); + Map callBackInput = createAppInput(id, null, "delete"); manageHttpAsyncClientPost(manageTypeApp, jsonRequest, new AppHttpCallBack(response, callBackInput)); } @@ -384,9 +405,12 @@ public void delApp(AppEntity appEntity, @Suspended AsyncResponse response) throw @Path("delGroup") public void delGroup(GroupEntity groupEntity, @Suspended AsyncResponse response) throws Exception { + String id = XSSFilter(groupEntity.getId()); + String groupId = XSSFilter(groupEntity.getGroupid()); + String ldapKey = XSSFilter(groupEntity.getLdapkey()); String time = df.format(new Date()); Map where = new HashMap(); - where.put("groupid", groupEntity.getGroupid()); + where.put("_id", id); Map cloumns = new HashMap(); cloumns.put("state", 0); @@ -400,7 +424,7 @@ public void delGroup(GroupEntity groupEntity, @Suspended AsyncResponse response) data.put("where", where); data.put("update", set); Map jsonRequest = createHttpMapRequest(bussinessTypeModify, data); - Map callBackInput = createInput(groupEntity.getGroupid(), null, "delete"); + Map callBackInput = createGroupInput(groupId,ldapKey, null, "delete"); manageHttpAsyncClientPost(manageTypeGroup, jsonRequest, new GroupHttpCallBack(response, callBackInput)); } @@ -510,18 +534,31 @@ private String getWebProName(HttpServletRequest request) { return requestUrl.substring(0, index); } - private Map createInput(String id, String value, String bType) { + private Map createAppInput(String id, String value, String bType) { Map input = new HashMap(); input.put("region", "apphub.gui.cache"); - input.put("appKey", "manage.app"); - input.put("groupKey", "manage.group"); + input.put("region.appKey", "manage.app"); + input.put("region.groupKey", "manage.group"); input.put("id", id); input.put("value", value); input.put("bType", bType); return input; } + private Map createGroupInput(String groupId, String ldappKey, String value, String bType) { + + Map input = new HashMap(); + input.put("region", "apphub.gui.cache"); + input.put("region.appKey", "manage.app"); + input.put("region.groupKey", "manage.group"); + input.put("groupId", groupId); + input.put("ldappKey", ldappKey); + input.put("value", value); + input.put("bType", bType); + return input; + } + // tools end----------------------------------------------------------> /** @@ -571,16 +608,13 @@ public AppHttpCallBack(AsyncResponse asyncResponseParam, Map inp void after(HttpClientCallbackResult result) { String id = input.get("id"); - String appKey = input.get("appKey"); String region = input.get("region"); + String regionAppKey = input.get("region.appKey"); String bType = input.get("bType"); String appUrl = input.get("value"); - logger.info(this, "ManageRestService AppHttpCallBack : region=" + region + ",key=" + appKey + ",id=" + id - + ",value=" + appUrl + ",type=" + bType); - if ("delete".equals(bType)) { - cm.delHash(region, appKey, id); + cm.delHash(region, regionAppKey, id); } else if ("modify".equals(bType) || "create".equals(bType)) { @@ -600,7 +634,6 @@ else if ("modify".equals(bType) || "create".equals(bType)) { Properties properties; try { - logger.info(this, "UAV管理 APP管理(添加or修改) app 配置加载 :" + configUrl); properties = PropertiesHelper.downloadProperties(configUrl); } catch (Exception e) { @@ -619,7 +652,7 @@ else if ("modify".equals(bType) || "create".equals(bType)) { resultJson.put("menu", jsonArray); String dataStr = JSONHelper.toString(resultJson); - cm.putHash(region, appKey, id, dataStr); + cm.putHash(region, regionAppKey, id, dataStr); } @@ -636,19 +669,20 @@ public GroupHttpCallBack(AsyncResponse asyncResponseParam, Map i @Override void after(HttpClientCallbackResult result) { - String id = input.get("id"); - String groupKey = input.get("groupKey"); String region = input.get("region"); + String regionAppKey = input.get("region.groupKey"); String bType = input.get("bType"); + + String groupId = input.get("groupId"); + String ldappKey = input.get("ldappKey"); String value = input.get("value"); - logger.info(this, "ManageRestService GroupHttpCallBack : region=" + region + ",key=" + groupKey + ",id=" - + id + ",value=" + value + ",type=" + bType); + String cacheId = "groupId:" + groupId + ",ldappKey:" + ldappKey; if ("delete".equals(bType)) { - cm.delHash(region, groupKey, id); + cm.delHash(region, regionAppKey, cacheId); } else if ("modify".equals(bType) || "create".equals(bType)) { - cm.putHash(region, groupKey, id, value); + cm.putHash(region, regionAppKey, cacheId, value); } } diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/entity/GroupEntity.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/entity/GroupEntity.java index 27fe73a3..d55c2a66 100644 --- a/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/entity/GroupEntity.java +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/manage/rest/entity/GroupEntity.java @@ -24,8 +24,9 @@ * @author Created by lbay on 2016/4/14. */ public class GroupEntity { - + private String id; private String groupid; + private String ldapkey; private String appids; private int state; private String createtime; @@ -34,6 +35,16 @@ public class GroupEntity { private String pageindex; private String pagesize; + public String getId() { + + return id; + } + + public void setId(String id) { + + this.id = id; + } + public String getGroupid() { return groupid; @@ -44,6 +55,16 @@ public void setGroupid(String groupid) { this.groupid = groupid; } + public String getLdapkey() { + + return ldapkey; + } + + public void setLdapkey(String ldapkey) { + + this.ldapkey = ldapkey; + } + public String getAppids() { return appids; @@ -114,12 +135,4 @@ public void setPagesize(String pagesize) { this.pagesize = pagesize; } - @Override - public String toString() { - - return "GroupEntity [groupid=" + groupid + ", appids=" + appids + ", state=" + state + ", createtime=" - + createtime + ", operationtime=" + operationtime + ", operationuser=" + operationuser + ", pageindex=" - + pageindex + ", pagesize=" + pagesize + "]"; - } - } diff --git a/com.creditease.uav.console/src/main/java/com/creditease/uav/timer/TimerServlet.java b/com.creditease.uav.console/src/main/java/com/creditease/uav/timer/TimerServlet.java new file mode 100644 index 00000000..ef6ffaa9 --- /dev/null +++ b/com.creditease.uav.console/src/main/java/com/creditease/uav/timer/TimerServlet.java @@ -0,0 +1,90 @@ +/*- + * << + * UAVStack + * == + * Copyright (C) 2016 - 2017 UAVStack + * == + * Licensed 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.creditease.uav.timer; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +import javax.servlet.http.HttpServlet; + +import com.creditease.agent.helpers.JSONHelper; +import com.creditease.agent.helpers.NetworkHelper; +import com.creditease.agent.log.SystemLogger; +import com.creditease.agent.log.api.ISystemLogger; + +/** + * TimerServlet description: apphub的任务调度 + */ +public class TimerServlet extends HttpServlet { + + private static final long serialVersionUID = 8252474547216672145L; + private ISystemLogger logger = null; + private Timer timer = null; + + @Override + public void init() { + + if (null == logger) { + logger = SystemLogger.getLogger(TimerServlet.class); + } + + if (null == timer) { + timer = new Timer(); + } + + timer.schedule(new LoggerPointTask(), 0, 1000 * 60);// 0秒后开始, 每次间隔1分钟 + + } + + @Override + public void destroy() { + + super.destroy(); + if (null != timer) { + timer.cancel(); + } + + } + + private class LoggerPointTask extends TimerTask { + + @Override + public void run() { + + SimpleDateFormat format = new SimpleDateFormat("mm"); + int minute = Integer.parseInt(format.format(new Date())); + int diff = minute % 5; + if (0 == diff) { + /** + * 当前分钟为5,10,15,20....55,60才会计数:1小时只有12条log打印 + */ + Map info = new HashMap(); + info.put("key", "apphubLogPoint"); + info.put("localIp", NetworkHelper.getLocalIP()); + logger.info(this, JSONHelper.toString(info)); + + } + } + } +} diff --git a/com.creditease.uav.console/src/main/webapp/WEB-INF/web.xml b/com.creditease.uav.console/src/main/webapp/WEB-INF/web.xml index 97d26832..2e6af654 100644 --- a/com.creditease.uav.console/src/main/webapp/WEB-INF/web.xml +++ b/com.creditease.uav.console/src/main/webapp/WEB-INF/web.xml @@ -24,6 +24,15 @@ jersey-serlvet /rs/* + + + + + apphubTimer + com.creditease.uav.timer.TimerServlet + 2 + + es-serlvet @@ -32,7 +41,7 @@ es.info {"forwar.url":"http://localhost:9200"} - 2 + 3 true @@ -44,7 +53,7 @@ opentsdb-agent-servlet com.creditease.uav.opentsdb.OpenTSDBRestAgentServlet - 3 + 4 true @@ -61,7 +70,6 @@ /db2/ /db2/aggregators - @@ -113,10 +121,6 @@ uav.app.manage.redis.store.addr localhost:6379 - - uav.app.ldap.redis.store.addr - localhost:6379 - uav.app.godeye.redis.store.addr localhost:6379 @@ -133,10 +137,6 @@ uav.app.manage.redis.store.params {"min":50,"max":200,"queue":5,"pwd":""} - - uav.app.ldap.redis.store.params - {"min":30,"max":100,"queue":5,"pwd":""} - uav.app.godeye.redis.store.params {"min":30,"max":100,"queue":5,"cacheaccess":5,"pwd":""} @@ -215,7 +215,7 @@ uav.app.godeye.notify.mongodb.query.range - {"skip":0,"limit":20000} + {"skip":0,"limit":1000} uav.apphub.sso.admin.loginid @@ -241,7 +241,7 @@ uav.apphub.sso.ldap.connection.info - {"url":"ldap://127.0.0.1:389/","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} + {"url":"ldap://127.0.0.1:389/","timeout":"1000","retry":"5","loginbasedn":"","querybasedn":"","user":"","password":"","suffix":"","primaryKey":"userPrincipalName","groupKey":"memberOf","groupTag":"邮件通讯组List","memberKey":"member","groupQueryField":"mail","userQueryField":"mail"} diff --git a/com.creditease.uav.console/src/main/webapp/apphub/js/app.temp.js b/com.creditease.uav.console/src/main/webapp/apphub/js/app.temp.js index 319cc470..1231ef2a 100644 --- a/com.creditease.uav.console/src/main/webapp/apphub/js/app.temp.js +++ b/com.creditease.uav.console/src/main/webapp/apphub/js/app.temp.js @@ -24,6 +24,8 @@ function LoadSidebarMenu(appInfo){ var key = "jumpurl@"; var begin = clickUrl.indexOf(key)+key.length; clickUrl = clickUrl.substring(begin); + + window["sidebarMenuType"] = "jumpurl"; } paraA.setAttribute("onclick","javascript:sidebarMenuOnclick(this,'"+clickUrl+"','"+appInfo.menu[j].functions+"')"); @@ -54,7 +56,6 @@ function LoadNavbarMenu(appInfo){ function jumpUrl(url,desc){ guiPing_RSClient(jumpUrlCallBack(url),"menuclick",url,desc); - //jumpUrlCallBack(url); } function jumpUrlCallBack(url){ @@ -75,19 +76,29 @@ function jumpUrlCallBack(url){ */ setContentHeight(); - if(url.indexOf("?")==-1) { - url += "?r="+uavRandom(9999,1); /*刷新,处理缓存*/ - } - else { - url +="&r="+uavRandom(9999,1); /*刷新,处理缓存*/ - } - console.log(document.getElementById("appContent").contentWindow.document.body.innerText); + /** + * 用户数据穿透 begin + * + * 是跳转菜单,则获取apphub信息 ,因为跳转表示不是apphub自应用。 + * 如果是apphub自应用,不需要透传信息,因为都可以在自应用拿到。 + */ + if(window["sidebarMenuType"] && "jumpurl"==window["sidebarMenuType"] ){ + loadApphubInfoByAES_RSClient(); + if(url.indexOf("?")==-1) { + url += "?apphubkey="+window["apphubAesInfo"]; + } + else { + url +="&apphubkey="+window["apphubAesInfo"]; + } + } + /** + * 用户数据穿透 end + * @returns + */ document.getElementById("appContent").contentWindow.document.body.innerText = ""; - - console.log(document.getElementById("appContent").contentWindow.document.body.innerText); - + $("#appContent").attr("src",url); $("#navbar").removeClass("in"); diff --git a/com.creditease.uav.console/src/main/webapp/apphub/js/common/mvc.js b/com.creditease.uav.console/src/main/webapp/apphub/js/common/mvc.js index 8d12f561..512d620c 100644 --- a/com.creditease.uav.console/src/main/webapp/apphub/js/common/mvc.js +++ b/com.creditease.uav.console/src/main/webapp/apphub/js/common/mvc.js @@ -113,6 +113,10 @@ function AppHubMVC(_mvcConfig) { var searchObj=mvcConfig["search"]; var searchKeyword=searchObj["keyword"]; + var hasSearchKey = undefined!=searchKeyword&&""!=searchKeyword&&"@ALL"!=searchKeyword; + if(hasSearchKey) { + var searchKeys = searchKeyword.split(" "); + } for(var i=0;i0) { - if (undefined!=searchKeyword&&""!=searchKeyword&&"@ALL"!=searchKeyword) { + if (hasSearchKey) { var ismeet=false; @@ -231,9 +235,11 @@ function AppHubMVC(_mvcConfig) { continue; } //meet the search condition - if (value.indexOf(searchKeyword)>-1) { - ismeet=true; - break; + for(var skIdx = 0; skIdx < searchKeys.length; skIdx++) { + if (searchKeys[skIdx] != undefined && searchKeys[skIdx] != "" && value.indexOf(searchKeys[skIdx])>-1) { + ismeet=true; + break; + } } } diff --git a/com.creditease.uav.console/src/main/webapp/apphub/js/main.temp.js b/com.creditease.uav.console/src/main/webapp/apphub/js/main.temp.js index 3de775e1..a2255da9 100644 --- a/com.creditease.uav.console/src/main/webapp/apphub/js/main.temp.js +++ b/com.creditease.uav.console/src/main/webapp/apphub/js/main.temp.js @@ -168,7 +168,7 @@ $("document").ready( * userlogger记录,通过用ping提交到filter begin * 同时会进行会话check(ping逻辑) */ - guiPing_RSClient(mainTempInit(),"jumpmain","","") + guiPing_RSClient(mainTempInit(),"jumpmain","","主页") /** * userlogger记录,通过用ping提交到filter end * diff --git a/com.creditease.uav.console/src/main/webapp/apphub/js/uav.restful.client.js b/com.creditease.uav.console/src/main/webapp/apphub/js/uav.restful.client.js index 5f5a3e3d..ea998488 100644 --- a/com.creditease.uav.console/src/main/webapp/apphub/js/uav.restful.client.js +++ b/com.creditease.uav.console/src/main/webapp/apphub/js/uav.restful.client.js @@ -227,6 +227,31 @@ function guiPing_RSClient(func,type,url,desc) { } +/** + * 获取apphub信息(信息经过加密) + * 同步方法,调用后会将结果写在window + */ +function loadApphubInfoByAES_RSClient() { + + AjaxHelper.call({ + url: restfulUrl +"loadApphubInfoByAES" , + data: {}, + async: false, + cache: false, + type: "GET", + dataType: "html", + success: function (result) { + var resultObj = eval("(" + result + ")"); + if (resultObj.CODE == "SUCCESS") { + window["apphubAesInfo"] = resultObj.DATA; + } + }, + error: function (result) { + reloadErrorContent("loadApphubInfoByAES_RSClient",result); + }, + }); +} + function loginOut_RSClient(){ AjaxHelper.call({ url: restfulUrl +"loginOut", diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/css/uav.appmonitor.css b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/css/uav.appmonitor.css index 5d91a127..74b9c967 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/css/uav.appmonitor.css +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/css/uav.appmonitor.css @@ -491,6 +491,11 @@ select{ color:#333; } +.IvcHighLightKeyword { + background:yellow; + color:#333; +} + .pluginAlertNtfy { width: 30px; height: 30px; diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.apm.js b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.apm.js index 8f545fa9..2a1b40c4 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.apm.js +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.apm.js @@ -158,7 +158,7 @@ function APMTool(app) { openDelete : false, key : "traceid", pagerSwitchThreshold : 600, - pagesize : 100, + pagesize : 50, deleteCtr : { key : "state", showDelete : "0" @@ -304,6 +304,54 @@ function APMTool(app) { if(params.appid=="ROOT"){ appurl = "http://"+params.ipport+"/"; } + + var results = _this.getProfileByAppurl(appurl); + //连接失败 + if(results == undefined){ + alert("获取日志文件失败"); + return; + } + //第一次没有获取到日志,把appurl中的appname去掉后再尝试获取一次 + if(results.rs == undefined){ + appurl = "http://"+params.ipport+"/"; + results = _this.getProfileByAppurl(appurl); + + //仍然没有获取到日志文件信息,此时profile中没有该appurl对应的信息,应该是由于应用停掉了 + if(results == undefined || results.rs == undefined){ + alert("获取日志文件失败,请检查应用是否处于运行状态"); + return; + } + } + + var res = results["rs"]; + var datas = StringHelper.str2obj(res); + + var data; + for(var key in datas){ + data = datas[key]; + } + var logdata = StringHelper.str2obj(data)["logs.log4j"]; + var logObj = StringHelper.str2obj(logdata); + for(var key in logObj){ + if(key.lastIndexOf("/") > 0){ + key = key.substring(key.lastIndexOf("/") + 1); + } + $("#logSelector").append(""); + } + if($("#logSelector option").size()>0){ + $("#selectLogWinfooter").append( ''); + }else{ + $("#logSelector").append(""); + } + $("#selectLogWinfooter").append( ''); + + + $("#selectLogWin").modal({backdrop:false}); + } + + + this.getProfileByAppurl = function(appurl){ + var results = undefined; AjaxHelper.call({ url: '../../rs/godeye/profile/q/cache', data: {"fkey":"appurl","fvalue":appurl}, @@ -311,36 +359,13 @@ function APMTool(app) { type: 'GET', dataType: 'html', timeout: 30000, + async: false, success: function(result){ - var obj = StringHelper.str2obj(result); - var res = obj["rs"]; - var datas = StringHelper.str2obj(res); - var data; - for(var key in datas){ - data = datas[key]; - } - var logdata = StringHelper.str2obj(data)["logs.log4j"]; - var logObj = StringHelper.str2obj(logdata); - for(var key in logObj){ - if(key.lastIndexOf("/") > 0){ - key = key.substring(key.lastIndexOf("/") + 1); - } - $("#logSelector").append(""); - } - if($("#logSelector option").size()>0){ - $("#selectLogWinfooter").append( ''); - }else{ - $("#logSelector").append(""); - } - $("#selectLogWinfooter").append( ''); - }, - error: function(result){ - $("#logSelector").append(""); - $("#selectLogWinfooter").append( ''); + results = StringHelper.str2obj(result); } - }); + }); - $("#selectLogWin").modal({backdrop:false}); + return results; } /** @@ -478,34 +503,39 @@ function APMTool(app) { "
"+ ""; - html+="
"; + html+="
"; } //全局模式 else { - html="
" + html="
" html+= "
应用实例
"; } - html+="
时间
" - + "" + html+="
" + + "时间" + "" + "" + + "
" - + "" - - + "
"; - -// + "
搜索 " + + "" + + "
"; html+=" "+ " " + " " + - " " ; + " 
" ; html+="
"; @@ -552,6 +582,16 @@ function APMTool(app) { app.controller.showWindow({traceid:id,comeFrom:"IVC"},"AppIVCTraceWnd","buildAppIVCTraceWnd","runAppIVCTraceWnd"); }; + // 分页事件 + this.mainList.sendRequest=function() { + + var pInfo=_this.mainList.getPagingInfo(); + + var start=(pInfo.pageNum-1)*pInfo.pageSize; + + _this.callIVCQuery("qsearch",{},{from:start,size:pInfo.pageSize}); + }; + //init datetime picker $('.form_datetime').datetimepicker({ language : 'zh-CN', @@ -672,6 +712,13 @@ function APMTool(app) { } + /** + * 跳转查询帮助界面 + */ + this.openHelpDiv = function() { + window.open("https://uavorg.github.io/documents/uavdoc_useroperation/59.html#%E6%9F%A5%E8%AF%A2%E5%B8%AE%E5%8A%A9","apphub.help"); + } + /** * 跳转到日志搜索结果页 */ @@ -862,7 +909,7 @@ function APMTool(app) { var errMsg = "无数据,请刷新重试"; var epinfo = sObj["epinfo"].split(",")[0]; //当前支持的类型 - var epinfos = ["http.service","apache.http.Client","apache.http.AsyncClient","mq.service","rabbitmq.client","jdbc.client","method","dubbo.provider","dubbo.consumer"]; + var epinfos = ["http.service","apache.http.Client","apache.http.AsyncClient","mq.service","rabbitmq.client","jdbc.client","method","dubbo.provider","dubbo.consumer","rocketmq.client"]; if($.inArray(epinfo, epinfos)==-1){ errMsg = "不支持的数据类型"; } @@ -886,8 +933,17 @@ function APMTool(app) { } // 必须先显示分页 - list.setTotalRow(count); - list.renderPagination(); + list.setTotalRow(totalCount); + list.renderPagination(); + + var keywords = this.getHighlightKeywords(); + + if(params == undefined && keywords != undefined){ + for(var type in keywords){ + this.setKeywordsHighlight(type,keywords[type],datas); + } + } + list.addTreeTableRows(datas); // only AppIVCTraceWnd_TraceList need treetable @@ -899,6 +955,70 @@ function APMTool(app) { //diaplay the Root Node $("#AppIVCTraceWnd_TraceList").treetable("expandNode","1"); } + + if(datas.length > 50){ + list.hidePagerPagination(); + } + }; + + this.getHighlightKeywords=function() { + + var content = this.parseKeyword(); + + if(content == undefined){ + return; + } + + var contents = content.split(","); + + var result = {}; + + for (var i = 0;i < contents.length;i++){ + + this.getKeywordArray(contents[i],result); + + } + + return result; + }; + + this.getKeywordArray = function(contents,result){ + if(contents.indexOf("=") == -1){ + return; + } + + var keywords = []; + var ctn = contents.split("="); + var orkwds=ctn[1].replace(/\"/g,"").split(" "); + + for(var i=0;i -1) { + lines=datas[j][type].split(keywords[i]); + datas[j][type] = lines.join(""+keywords[i]+""); + } + } + } }; // TODO ----------------------------------调用链查看窗口:全局模式专有--------------------- this.profileDAO=new UAVProfileDAO(); @@ -1076,7 +1196,7 @@ function APMTool(app) { /** * 访问调用链查询服务 */ - this.callIVCQuery=function(intent,pObj) { + this.callIVCQuery=function(intent,pObj,cursor) { var data={intent:"qApp",request:{}}; @@ -1095,7 +1215,12 @@ function APMTool(app) { appuuid=this.appInfo["appuuid"]; } else { - appuuid=pObj["appuuid"]; + appuuid=this.appInfo["appuuid"]; + } + + var content = this.parseKeyword(); + if(content != undefined){ + data["request"]["content"] = content; } switch(intent) { @@ -1109,7 +1234,7 @@ function APMTool(app) { if (timeRange==undefined) { var tmp=new Date().getTime(); - timeRange={etime:tmp,stime:tmp-60000}; + timeRange={etime:tmp,stime:tmp-60000*60}; } var etime=timeRange["etime"]; @@ -1119,9 +1244,17 @@ function APMTool(app) { data["request"]["etime"]=etime+""; data["request"]["eptype"]="E,S"; data["request"]["from"]=0+""; - data["request"]["size"]=500+""; + data["request"]["size"]=50+""; data["request"]["indexdate"]=timeRange["indexdate"]; + if (cursor != undefined){ + data["request"]["from"]=cursor.from+""; + data["request"]["size"]=cursor.size+""; + } + else{ + dataList.setPageNum(1); + } + var timeSort=this.timeSortSelector.value(); if (timeSort=="DESC") { data["request"]["sort"]="stime=DESC"; @@ -1140,7 +1273,7 @@ function APMTool(app) { data["request"]["etime"]=etime+""; data["request"]["eptype"]="E,S"; data["request"]["from"]=0+""; - data["request"]["size"]=100+""; + data["request"]["size"]=50+""; break; case "lst100": dataList=this.mainList; @@ -1206,7 +1339,7 @@ function APMTool(app) { var obj = StringHelper.str2obj(result); var res = obj["rs"]; - if (obj=="ERR"||res=="ERR") { + if (obj=="ERR"||res=="ERR"||res==undefined) { alert("调用链查询操作["+intent+"]失败:"+result); } else { @@ -1231,6 +1364,50 @@ function APMTool(app) { }); }; + this.getKeyword=function() { + + var keys=""; + + if (HtmlHelper.id("AppIVCWnd_KeyWord")!=undefined&&HtmlHelper.id("AppIVCWnd_KeyWord").value!="") { + keys=HtmlHelper.id("AppIVCWnd_KeyWord").value; + } + + return keys; + }; + + /** + * 把keyword转换成后台需要的格式url="xxx",stat="xxx",class="xxx" + */ + this.parseKeyword=function(){ + + var keyword = this.getKeyword(); + if(keyword == ""){ + return; + } + + //如果是类似method="**"直接返回 + if(keyword.indexOf("=") > -1 && keyword.indexOf("\"") > -1){ + return keyword; + } + //不包含@标识,当作url关键字 + if(keyword.indexOf("@") == -1){ + return "url=\"" + keyword + "\""; + } + //以@标识开头,当作state关键字 + if(keyword.startsWith("@")){ + return "state=\"" + keyword.substring(1) + "\""; + } + //@标识符超过一个,目前先当作url关键字 + var keywords = keyword.split("@"); + if(! keywords.length == 2){ + return "url=\"" + keyword + "\""; + } + //@标识符只有一个,@前面的为url关键字,后边的为state关键字 + var content = "url=\"" + keywords[0] + "\""; + content += ",state=\"" + keywords[1] + "\""; + return content; + }; + /** * 访问重调用链查询服务 */ diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.appmonitor.js b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.appmonitor.js index 465e506d..5cb68794 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.appmonitor.js +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/appmonitor/js/uav.appmonitor.js @@ -1375,13 +1375,18 @@ var mvcObj={ nodeInfoObj["id"]=key; var appgroup=nodeInfoObj["appgroup"]; + var appid=nodeInfoObj["appid"]; if (appgroup==undefined||appgroup=="") { ungroupNodes[ungroupNodes.length]=nodeInfoObj; } else { var ip=nodeInfoObj["ip"]; - ipToAppGroup[ip]=appgroup; + if(ipToAppGroup[ip]==undefined){ + ipToAppGroup[ip]=[]; + } + + ipToAppGroup[ip][appid]=appgroup; } nodeArray[nodeArray.length]=nodeInfoObj; @@ -1391,8 +1396,8 @@ var mvcObj={ for(var i=0;i来源"); sb.append("
  • "+objattr.nodename.n+""+objattr.nodename.v+"("+objattr.nodeuuid.v+")
  • "); sb.append( "
  • "+objattr.component.n+""+objattr.feature.v+"."+objattr.component.v+"
  • "); + sb.append( "
  • "+objattr.strategydesc.n+""+objattr.strategydesc.v+"
  • "); sb.append( "
  • "+objattr.desc.n+"
    "+issueDesc+"
  • "); sb.append( "
    " /*用于后续扩充收缩功能*/); sb.append( "
  • 上下文信息
  • "); diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/css/uav.notifystgy.css b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/css/uav.notifystgy.css index 6d992646..88785035 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/css/uav.notifystgy.css +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/css/uav.notifystgy.css @@ -103,7 +103,7 @@ body { border-radius: 3px; box-shadow: 0 0 1px 1px #000000; } -.icon-myout,.icon-myhelp { +.icon-myout,.icon-myhelp,.icon-mycopy { float: right; margin-top: 5px; margin-right: 15px; @@ -126,6 +126,16 @@ body { box-shadow: 0 0 4px 4px #ffffff; } +.icon-mycopy{ + height: 31.4px; + width: 31.4px; + + } +.icon-mycopy:hover{ + border-radius: 3px; + box-shadow: 0 0 4px 4px #ffffff; +} + .titleDiv { font-size: 16px; color: #ffffff; @@ -299,6 +309,26 @@ body { color:darkgrey; } +.StgyDiv .edit-div-option{ + font-size: 14px; + height: 50px; + width: 95%; + min-width: 340px; + border-radius: 2px; + border-color:#000000; + margin: 0 auto; + text-align:left; + padding: 5px; + margin-top: 5px; + overflow-y:auto; + color:#000000; +} + +StgyDiv .edit-div-option:empty:before{ + content: attr(placeholder); + color:darkgrey; +} + .whereStgyEdit{ border-radius: 4px; } @@ -353,3 +383,21 @@ body { /** *触发策略 end */ + +.itemTitle { + text-align:left; + color:#333; + border-left:6px solid #57A69C; + padding-left:5px; + margin-bottom:2px; +} + +.itemTip { + color:gray; + font-size:14px; + text-align:left; +} + +.dateTimeInput { + width:120px; +} \ No newline at end of file diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.add.js b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.add.js index 1f01aa7e..b1551727 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.add.js +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.add.js @@ -124,6 +124,7 @@ function saveNotify(checkIsExist){ */ //校验 var stgyExpHtmlObjs = document.getElementsByName("stgy_exp_html"),stgyExpCheck=true; + var stgyConvergences = document.getElementsByName("stgy_convergence_html"); if(stgyExpHtmlObjs.length==0 && mName != "procCrash"){ $("#addNotifyErrMSG").text("触发策略不能为空"); return false; @@ -140,7 +141,7 @@ function saveNotify(checkIsExist){ } //赋值 - var relations=[],relationsHtmls = []; + var relations=[],relationsHtmls = [],convergences=[]; $.each(stgyExpHtmlObjs,function(index,obj){ var relation = obj.innerText; var resultHtml = obj.innerHTML; @@ -152,6 +153,7 @@ function saveNotify(checkIsExist){ relations[index]= relation;//赋值表达式 relationsHtmls[index]= resultHtml;//赋值用户操作html + convergences[index] = stgyConvergences[index].innerText; }); /** @@ -187,7 +189,8 @@ function saveNotify(checkIsExist){ "action":actions, "owner":owner, "relations":relations, - "relationsHtmls":relationsHtmls + "relationsHtmls":relationsHtmls, + "convergences":convergences } commitInfo[fName]=result; saveKey = fName; diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.edit.js b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.edit.js index b4db82f3..11339db2 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.edit.js +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.edit.js @@ -3,5 +3,5 @@ function showEditDiv(id,obj){ } function showEditDivIsReadOnly(jsonObj){ - showEditNotifyDiv(jsonObj); + showEditNotifyDiv(jsonObj,false); } \ No newline at end of file diff --git a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.win.js b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.win.js index 250f26d2..e0fd5689 100644 --- a/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.win.js +++ b/com.creditease.uav.console/src/main/webapp/uavapp_godeye/notifystgy/js/notifystgy.win.js @@ -156,7 +156,7 @@ function showAddDiv() { sb.append( '
    '); - sb.append( '
    '); + sb.append( '
    '); sb.append( '
    '); sb.append( '
    条件定义
    '); @@ -172,6 +172,7 @@ function showAddDiv() { sb.append( '
    '); sb.append( '
    '); + sb.append( '
     
    '); sb.append( '
    '); @@ -186,7 +187,7 @@ function showAddDiv() { /** * 显示编辑策略 */ -function showEditNotifyDiv(jsonObjParam) { +function showEditNotifyDiv(jsonObjParam,isCopy) { var key,jsonObj,isOwner=false;enableThreadAnalysis=false; //因为只有一对 key:value 获取key(值为id) @@ -195,6 +196,12 @@ function showEditNotifyDiv(jsonObjParam) { jsonObj = obj; }); + if(isCopy==true){ + jsonObj.owner=window.parent.loginUser.userId; + }else{ + actionConf.actionObj=jsonObjParam; + } + if(jsonObj.owner == window.parent.loginUser.userId || window.parent.loginUser.groupId == "uav_admin" || window.parent.loginUser.groupId == "vipgroup" @@ -207,9 +214,20 @@ function showEditNotifyDiv(jsonObjParam) { var sb=new StringBuffer(); sb.append( "
    "); sb.append( ""); - sb.append( "编辑策略"); + + if(isCopy){ + sb.append( "编辑复制策略"); + }else{ + sb.append( "编辑策略"); + } + sb.append( "
    "); sb.append( "
    "); + + if(!isCopy){ + sb.append( "
    "); + } + sb.append( "
    "); sb.append( "
    "); /** @@ -249,8 +267,12 @@ function showEditNotifyDiv(jsonObjParam) { if(showNameF=="自定义指标"){ selUiConf["userInput"]["notifyNameM"]=names[1];//编辑赋值,准备修改数据 }else if(names[1] == "log"){ - sb.append( '
    '); - selUiConf["userInput"]["notifyNameM"]=names[1];//编辑赋值,准备修改数据 + if(isCopy){ + sb.append( '
    '); + }else{ + sb.append( '
    '); + selUiConf["userInput"]["notifyNameM"]=names[1];//编辑赋值,准备修改数据 + } }else if(names[1]){ sb.append( '
    '); selUiConf["userInput"]["notifyNameM"]=names[1];//编辑赋值,准备修改数据 @@ -261,14 +283,26 @@ function showEditNotifyDiv(jsonObjParam) { //3 if(names[2] && names[1] == "log"){ var nNameIShow = "指定日志:"+names[2]; - sb.append( '
    '); - selUiConf["userInput"]["notifyNameI"]=names[2];//编辑赋值,准备修改数据 + if(isCopy){ + sb.append( '
    '); + }else{ + sb.append( '
    '); + selUiConf["userInput"]["notifyNameI"]=names[2];//编辑赋值,准备修改数据 + } }else if(names[1] == "log"){ - sb.append( '
    '); + if(isCopy){ + sb.append( '
    '); + }else{ + sb.append( '
    '); + } }else if(names[2]){ var nNameIShow = (existsIns?"实例组:":"实例:")+names[2]; - sb.append( '
    '); - selUiConf["userInput"]["notifyNameI"]=names[2];//编辑赋值,准备修改数据 + if(isCopy){ + sb.append( '
    '); + }else{ + sb.append( '
    '); + selUiConf["userInput"]["notifyNameI"]=names[2];//编辑赋值,准备修改数据 + } }else{ sb.append( '
    '); } @@ -286,9 +320,9 @@ function showEditNotifyDiv(jsonObjParam) { sb.append( '
    '); if(isOwner){ - sb.append( '
    '); + sb.append( '
    '); }else{ - sb.append( '
    '); + sb.append( '
    '); } /** @@ -337,12 +371,18 @@ function showEditNotifyDiv(jsonObjParam) { if(jsonObj.relationsHtmls){ $.each(jsonObj.relationsHtmls,function(index,html){ + var convergenceVal = ""; + if(jsonObj.hasOwnProperty("convergences")){ + convergenceVal = jsonObj.convergences[index]; + } + var appendHtml = '
    '+ '
    '+ - '
    '+html+'
    '+ - '
    '; - + '
    '+html+'
    '+ + '
    '+convergenceVal+'
    '+ + '
    '; + if(isOwner){ appendHtml+=''; }else{ @@ -400,8 +440,13 @@ function showEditNotifyDiv(jsonObjParam) { if(isOwner){ //按钮 - sb.append( '
    '); + if(isCopy){ + sb.append( '
    '); + }else{ + sb.append( '
    '); + } sb.append( '
    '); + sb.append( '
     
    '); } sb.append( '
    '); @@ -541,24 +586,50 @@ function showCon(thisObj,type){ var hour=jsonValue.time_from.split(':')[0]; var min=jsonValue.time_from.split(':')[1]; - $('#time_start').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); + $('#time_from_div').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); hour=jsonValue.time_to.split(':')[0]; min=jsonValue.time_to.split(':')[1]; - $('#time_end').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); + $('#time_to_div').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); + + if(jsonValue.time_start!=undefined&&jsonValue.time_end!=undefined){ + hour=jsonValue.time_start.split(':')[0]; + min=jsonValue.time_start.split(':')[1]; + $('#time_start_div').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); + hour=jsonValue.time_end.split(':')[0]; + min=jsonValue.time_end.split(':')[1]; + $('#time_end_div').data('datetimepicker').setLocalDate(new Date(2000, 1, 1, hour, min)); + } + + if(jsonValue.day_start!=undefined&&jsonValue.day_end!=undefined){ + var year=jsonValue.day_start.split('-')[0]; + var month=jsonValue.day_start.split('-')[1]; + var day=jsonValue.day_start.split('-')[2]; + $('#day_start_div').data('datetimepicker').setLocalDate(new Date(year, month-1, day, 0, 0)); + year=jsonValue.day_end.split('-')[0]; + month=jsonValue.day_end.split('-')[1]; + day=jsonValue.day_end.split('-')[2]; + $('#day_end_div').data('datetimepicker').setLocalDate(new Date(year, month-1, day, 0, 0)); + } + + showWeekDay(jsonValue.weekdayLimit); $("#conMetric").val(jsonValue.metric); $("#conUpperLimit").val(jsonValue.upperLimit); $("#conLowerLimit").val(jsonValue.lowerLimit); $("#conAggr").val(jsonValue.aggr); + $("#conDownSample").val(jsonValue.downsample); if(type=="link-relative"){ - $("#conInterval").val(jsonValue.interval); - showUnit(jsonValue.unit); - }else{ - showUnit(jsonValue.unit); + $("#conInterval").val(jsonValue.interval); } + showUnit(jsonValue.unit); + if(isOwner!="true"){ $("#time_from").attr("readonly","readonly"); $("#time_to").attr("readonly","readonly"); + $("#time_start").attr("readonly","readonly"); + $("#time_end").attr("readonly","readonly"); + $("#day_start").attr("readonly","readonly"); + $("#day_end").attr("readonly","readonly"); $("#conMetric").attr("readonly","readonly"); $("#conUpperLimit").attr("readonly","readonly"); $("#conLowerLimit").attr("readonly","readonly"); @@ -566,6 +637,7 @@ function showCon(thisObj,type){ $("#conUpperLimit").attr("class","form-control"); $("#conLowerLimit").attr("class","form-control"); $("#conAggr").attr("disabled","disabled"); + $("#conDownSample").attr("disabled","disabled"); if(type=="link-relative"){ $("#conInterval").attr("readonly","readonly"); $("#conInterval").attr("class","form-control"); @@ -582,6 +654,16 @@ function showUnit(unit){ $("#unit").val(unit); $("#opt"+unit).attr("class","btn btn-default active"); } + +function showWeekDay(weekdayLimit){ + + for(var i=0;i'); - sb.append( '
    '); - sb.append( '
    '); - sb.append( "
    '); + sb.append( '
    持续时间(秒)

    '); + sb.append( "
    聚集操作
    '); + sb.append( '